iceshrimp/packages/client/src/components/MkMarquee.vue

109 lines
1.8 KiB
Vue
Raw Normal View History

<script lang="ts">
2023-04-08 09:01:42 +09:00
import { h, onMounted, onUnmounted, ref, watch } from "vue";
export default {
2023-04-08 09:01:42 +09:00
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();
function calc() {
const eachLength = contentEl.value.offsetWidth / props.repeat;
const factor = 3000;
const duration = props.duration / ((1 / eachLength) * factor);
contentEl.value.style.animationDuration = `${duration}s`;
}
2022-07-02 22:07:04 +09:00
watch(() => props.duration, calc);
onMounted(() => {
calc();
});
2023-04-08 09:01:42 +09:00
onUnmounted(() => {});
return {
contentEl,
};
},
2023-04-08 09:01:42 +09:00
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 {
2022-07-13 21:41:06 +09:00
overflow: clip;
2022-07-05 16:16:13 +09:00
animation-play-state: running;
&:hover {
animation-play-state: paused;
}
}
.content {
display: inline-block;
white-space: nowrap;
2022-07-05 16:16:13 +09:00
animation-play-state: inherit;
}
.text {
display: inline-block;
animation-name: marquee;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: inherit;
2022-07-05 16:16:13 +09:00
animation-play-state: inherit;
}
.paused .text {
animation-play-state: paused;
}
@keyframes marquee {
2023-04-08 09:01:42 +09:00
0% {
transform: translateX(0);
}
100% {
transform: translateX(-100%);
}
}
</style>