summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkMarqueeText.vue
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2025-05-11 15:43:16 +0900
committerGitHub <noreply@github.com>2025-05-11 15:43:16 +0900
commit3df421da1a27d76f11f3b43c8b1fc06f98ccdad6 (patch)
tree5d5cf1133c154c55483acef26c193e772a5340ea /packages/frontend/src/components/MkMarqueeText.vue
parent🎨 (diff)
downloadmisskey-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.vue89
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>