diff options
| author | Acid Chicken (硫酸鶏) <root@acid-chicken.com> | 2023-04-29 22:57:46 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-29 22:57:46 +0900 |
| commit | 9d5911d4e436859127f38d5fcdaa6cb5ce6d01e6 (patch) | |
| tree | 4feca3f9e8ed46acc0ee3abd7ad357c8d1f05d8e /packages/frontend/src/components/MkImgWithBlurhash.vue | |
| parent | fix(backend): `alsoKnownAs`の誤った定義を修正 (#10725) (diff) | |
| download | misskey-9d5911d4e436859127f38d5fcdaa6cb5ce6d01e6.tar.gz misskey-9d5911d4e436859127f38d5fcdaa6cb5ce6d01e6.tar.bz2 misskey-9d5911d4e436859127f38d5fcdaa6cb5ce6d01e6.zip | |
feat: make `MkImgWithBlurhash` transitionable (#10500)
* feat: make `MkImgWithBlurhash` animatable
* refactor: split out transition styles
* fix: bug
* test: waitFor image loads
* style: remove unused await
* fix
* fix type error
---------
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
Diffstat (limited to 'packages/frontend/src/components/MkImgWithBlurhash.vue')
| -rw-r--r-- | packages/frontend/src/components/MkImgWithBlurhash.vue | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/packages/frontend/src/components/MkImgWithBlurhash.vue b/packages/frontend/src/components/MkImgWithBlurhash.vue index 048dcc7045..2bdb059614 100644 --- a/packages/frontend/src/components/MkImgWithBlurhash.vue +++ b/packages/frontend/src/components/MkImgWithBlurhash.vue @@ -1,15 +1,37 @@ <template> <div :class="[$style.root, { [$style.cover]: cover }]" :title="title ?? ''"> - <canvas v-if="!loaded || forceBlurhash" ref="canvas" :class="$style.canvas" :width="width" :height="height" :title="title ?? ''"/> - <img v-if="src && !forceBlurhash" v-show="loaded" :class="$style.img" :src="src" :title="title ?? ''" :alt="alt ?? ''" @load="onLoad"/> + <img v-if="!loaded && src && !forceBlurhash" :class="$style.loader" :src="src" @load="onLoad"/> + <Transition + mode="in-out" + :enter-active-class="defaultStore.state.animation && (props.transition?.enterActiveClass ?? $style['transition_toggle_enterActive']) || undefined" + :leave-active-class="defaultStore.state.animation && (props.transition?.leaveActiveClass ?? $style['transition_toggle_leaveActive']) || undefined" + :enter-from-class="defaultStore.state.animation && props.transition?.enterFromClass || undefined" + :leave-to-class="defaultStore.state.animation && props.transition?.leaveToClass || undefined" + :enter-to-class="defaultStore.state.animation && props.transition?.enterToClass || undefined" + :leave-from-class="defaultStore.state.animation && props.transition?.leaveFromClass || undefined" + > + <canvas v-if="!loaded || forceBlurhash" ref="canvas" :class="$style.canvas" :width="width" :height="height" :title="title"/> + <img v-else :class="$style.img" :src="src ?? undefined" :title="title ?? undefined" :alt="alt ?? undefined"/> + </Transition> </div> </template> <script lang="ts" setup> -import { onMounted, watch } from 'vue'; +import { onMounted, shallowRef, useCssModule, watch } from 'vue'; import { decode } from 'blurhash'; +import { defaultStore } from '@/store'; + +const $style = useCssModule(); const props = withDefaults(defineProps<{ + transition?: { + enterActiveClass?: string; + leaveActiveClass?: string; + enterFromClass?: string; + leaveToClass?: string; + enterToClass?: string; + leaveFromClass?: string; + } | null; src?: string | null; hash?: string; alt?: string | null; @@ -19,6 +41,7 @@ const props = withDefaults(defineProps<{ cover?: boolean; forceBlurhash?: boolean; }>(), { + transition: null, src: null, alt: '', title: null, @@ -28,7 +51,7 @@ const props = withDefaults(defineProps<{ forceBlurhash: false, }); -const canvas = $shallowRef<HTMLCanvasElement>(); +const canvas = shallowRef<HTMLCanvasElement>(); let loaded = $ref(false); let width = $ref(props.width); let height = $ref(props.height); @@ -51,15 +74,15 @@ watch([() => props.width, () => props.height], () => { }); function draw() { - if (props.hash == null) return; + if (props.hash == null || !canvas.value) return; const pixels = decode(props.hash, width, height); - const ctx = canvas.getContext('2d'); + const ctx = canvas.value.getContext('2d'); const imageData = ctx!.createImageData(width, height); imageData.data.set(pixels); ctx!.putImageData(imageData, 0, 0); } -watch(() => props.hash, () => { +watch([() => props.hash, canvas], () => { draw(); }); @@ -69,6 +92,21 @@ onMounted(() => { </script> <style lang="scss" module> +.transition_toggle_enterActive, +.transition_toggle_leaveActive { + position: absolute; + top: 0; + left: 0; +} + +.loader { + position: absolute; + top: 0; + left: 0; + width: 0; + height: 0; +} + .root { position: relative; width: 100%; |