diff options
Diffstat (limited to 'packages/frontend/src/components/MkImgWithBlurhash.vue')
| -rw-r--r-- | packages/frontend/src/components/MkImgWithBlurhash.vue | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/packages/frontend/src/components/MkImgWithBlurhash.vue b/packages/frontend/src/components/MkImgWithBlurhash.vue new file mode 100644 index 0000000000..80d7c201a4 --- /dev/null +++ b/packages/frontend/src/components/MkImgWithBlurhash.vue @@ -0,0 +1,76 @@ +<template> +<div class="xubzgfgb" :class="{ cover }" :title="title"> + <canvas v-if="!loaded" ref="canvas" :width="size" :height="size" :title="title"/> + <img v-if="src" :src="src" :title="title" :alt="alt" @load="onLoad"/> +</div> +</template> + +<script lang="ts" setup> +import { onMounted } from 'vue'; +import { decode } from 'blurhash'; + +const props = withDefaults(defineProps<{ + src?: string | null; + hash?: string; + alt?: string; + title?: string | null; + size?: number; + cover?: boolean; +}>(), { + src: null, + alt: '', + title: null, + size: 64, + cover: true, +}); + +const canvas = $ref<HTMLCanvasElement>(); +let loaded = $ref(false); + +function draw() { + if (props.hash == null) return; + const pixels = decode(props.hash, props.size, props.size); + const ctx = canvas.getContext('2d'); + const imageData = ctx!.createImageData(props.size, props.size); + imageData.data.set(pixels); + ctx!.putImageData(imageData, 0, 0); +} + +function onLoad() { + loaded = true; +} + +onMounted(() => { + draw(); +}); +</script> + +<style lang="scss" scoped> +.xubzgfgb { + position: relative; + width: 100%; + height: 100%; + + > canvas, + > img { + display: block; + width: 100%; + height: 100%; + } + + > canvas { + position: absolute; + object-fit: cover; + } + + > img { + object-fit: contain; + } + + &.cover { + > img { + object-fit: cover; + } + } +} +</style> |