diff options
| author | かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> | 2025-05-11 15:43:16 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-11 15:43:16 +0900 |
| commit | 3df421da1a27d76f11f3b43c8b1fc06f98ccdad6 (patch) | |
| tree | 5d5cf1133c154c55483acef26c193e772a5340ea /packages/frontend/src/components/MkMarqueeText.vue | |
| parent | 🎨 (diff) | |
| download | misskey-3df421da1a27d76f11f3b43c8b1fc06f98ccdad6.tar.gz misskey-3df421da1a27d76f11f3b43c8b1fc06f98ccdad6.tar.bz2 misskey-3df421da1a27d76f11f3b43c8b1fc06f98ccdad6.zip | |
refactor(frontend): MkMarquee のコードの可読性の向上 (#16017)
* fix(frontend/MkMarquee): Composition API に移行
* move animation to scoped environment
* refactor
---------
Co-authored-by: taiyme <53635909+taiyme@users.noreply.github.com>
Diffstat (limited to 'packages/frontend/src/components/MkMarqueeText.vue')
| -rw-r--r-- | packages/frontend/src/components/MkMarqueeText.vue | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/packages/frontend/src/components/MkMarqueeText.vue b/packages/frontend/src/components/MkMarqueeText.vue new file mode 100644 index 0000000000..a2c365afe9 --- /dev/null +++ b/packages/frontend/src/components/MkMarqueeText.vue @@ -0,0 +1,89 @@ +<!-- +SPDX-FileCopyrightText: syuilo and misskey-project +SPDX-License-Identifier: AGPL-3.0-only +--> + +<template> +<div :class="$style.wrap"> + <span + ref="contentEl" + :class="[$style.content, { + [$style.paused]: paused, + [$style.reverse]: reverse, + }]" + > + <span v-for="key in repeat" :key="key" :class="$style.text"> + <slot></slot> + </span> + </span> +</div> +</template> + +<script lang="ts" setup> +import { onMounted, useTemplateRef, watch } from 'vue'; + +const props = withDefaults(defineProps<{ + duration?: number; + repeat?: number; + paused?: boolean; + reverse?: boolean; +}>(), { + duration: 15, + repeat: 2, + paused: false, + reverse: false, +}); + +const contentEl = useTemplateRef('contentEl'); + +function calcDuration() { + if (contentEl.value == null) return; + const eachLength = contentEl.value.offsetWidth / props.repeat; + const factor = 3000; + const duration = props.duration / ((1 / eachLength) * factor); + contentEl.value.style.animationDuration = `${duration}s`; +} + +watch(() => props.duration, calcDuration); + +onMounted(calcDuration); +</script> + +<style lang="scss" module> +.wrap { + overflow: clip; + animation-play-state: running; + + &:hover { + animation-play-state: paused; + } +} + +.content { + display: inline-block; + white-space: nowrap; + animation-play-state: inherit; +} + +.text { + display: inline-block; + animation-name: marquee; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-duration: inherit; + animation-play-state: inherit; +} + +.paused .text { + animation-play-state: paused; +} + +.reverse .text { + animation-direction: reverse; +} + +@keyframes marquee { + 0% { transform: translateX(0); } + 100% { transform: translateX(-100%); } +} +</style> |