2023-01-05 15:38:22 +03:00
|
|
|
<script setup lang="ts">
|
|
|
|
import { decode } from 'blurhash'
|
|
|
|
|
|
|
|
const { blurhash, src, srcset } = defineProps<{
|
2023-01-05 19:48:20 +03:00
|
|
|
blurhash?: string | null | undefined
|
2023-01-05 15:38:22 +03:00
|
|
|
src: string
|
|
|
|
srcset?: string
|
|
|
|
}>()
|
|
|
|
|
|
|
|
defineOptions({
|
|
|
|
inheritAttrs: false,
|
|
|
|
})
|
|
|
|
|
|
|
|
const isLoaded = ref(false)
|
2023-01-05 19:48:20 +03:00
|
|
|
const placeholderSrc = $computed(() => {
|
|
|
|
if (!blurhash)
|
|
|
|
return ''
|
|
|
|
const pixels = decode(blurhash, 32, 32)
|
|
|
|
return getDataUrlFromArr(pixels, 32, 32)
|
|
|
|
})
|
2023-01-05 15:38:22 +03:00
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
const img = document.createElement('img')
|
|
|
|
|
|
|
|
img.onload = () => {
|
|
|
|
isLoaded.value = true
|
|
|
|
}
|
|
|
|
|
|
|
|
img.src = src
|
|
|
|
|
|
|
|
if (srcset)
|
|
|
|
img.srcset = srcset
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
isLoaded.value = true
|
|
|
|
}, 3_000)
|
|
|
|
})
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
2023-01-13 09:19:46 +03:00
|
|
|
<Transition>
|
|
|
|
<img v-if="isLoaded || !placeholderSrc" v-bind="$attrs" :src="src" :srcset="srcset" absolute>
|
|
|
|
<img v-else v-bind="$attrs" :src="placeholderSrc" absolute>
|
|
|
|
</Transition>
|
|
|
|
<img v-bind="$attrs" :src="placeholderSrc" z-0 aria-hidden>
|
2023-01-05 15:38:22 +03:00
|
|
|
</template>
|
2023-01-13 09:19:46 +03:00
|
|
|
|
|
|
|
<style>
|
|
|
|
.v-enter-active {
|
|
|
|
transition: opacity 0.3s ease;
|
|
|
|
}
|
|
|
|
|
|
|
|
.v-enter-from {
|
|
|
|
opacity: 0;
|
|
|
|
}
|
|
|
|
</style>
|