98 lines
1.6 KiB
Vue
98 lines
1.6 KiB
Vue
|
<script lang="ts">
|
||
|
import { h, onMounted, onUnmounted, ref } 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();
|
||
|
|
||
|
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`;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
.content {
|
||
|
display: inline-block;
|
||
|
white-space: nowrap;
|
||
|
}
|
||
|
.text {
|
||
|
display: inline-block;
|
||
|
animation-name: marquee;
|
||
|
animation-timing-function: linear;
|
||
|
animation-iteration-count: infinite;
|
||
|
animation-duration: inherit;
|
||
|
}
|
||
|
.paused .text {
|
||
|
animation-play-state: paused;
|
||
|
}
|
||
|
@keyframes marquee {
|
||
|
0% { transform:translateX(0); }
|
||
|
100% { transform:translateX(-100%); }
|
||
|
}
|
||
|
</style>
|