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 | |
| 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')
| -rw-r--r-- | packages/frontend/src/components/MkMarquee.vue | 112 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkMarqueeText.vue | 89 |
2 files changed, 89 insertions, 112 deletions
diff --git a/packages/frontend/src/components/MkMarquee.vue b/packages/frontend/src/components/MkMarquee.vue deleted file mode 100644 index 4a89d21b92..0000000000 --- a/packages/frontend/src/components/MkMarquee.vue +++ /dev/null @@ -1,112 +0,0 @@ -<!-- -SPDX-FileCopyrightText: syuilo and misskey-project -SPDX-License-Identifier: AGPL-3.0-only ---> - -<script lang="ts"> -import { h, onMounted, onUnmounted, ref, watch } from 'vue'; - -export default { - name: 'MarqueeText', - props: { - duration: { - type: Number, - default: 15, - }, - repeat: { - type: Number, - default: 2, - }, - paused: { - type: Boolean, - default: false, - }, - reverse: { - type: Boolean, - default: false, - }, - }, - setup(props) { - const contentEl = ref<HTMLElement>(); - - function calc() { - 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, calc); - - onMounted(() => { - calc(); - }); - - onUnmounted(() => { - }); - - return { - contentEl, - }; - }, - render({ - $slots, $style, $props: { - duration, repeat, paused, reverse, - }, - }) { - return h('div', { class: [$style.wrap] }, [ - h('span', { - ref: 'contentEl', - class: [ - paused - ? $style.paused - : undefined, - $style.content, - ], - }, Array(repeat).fill( - h('span', { - class: $style.text, - style: { - animationDirection: reverse - ? 'reverse' - : undefined, - }, - }, $slots.default()), - )), - ]); - }, -}; -</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; -} -@keyframes marquee { - 0% { transform:translateX(0); } - 100% { transform:translateX(-100%); } -} -</style> 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> |