1. 新建组件RegionRoll.vue
<template>
<div :style="noticeStyle" ref="noticeDivRef">
<span ref="noticeRef" class="notice-span" :style="noticeSpanStyle">{{ props.text }}</span>
</div>
</template>
<script setup lang="ts">
import { computed, defineProps, onMounted, ref, nextTick, watch } from 'vue'
const props = defineProps({
/* 区域宽度(默认200px) */
w: {
type: String,
default: '200px'
},
/* 区域高度(默认20px) */
h: {
type: String,
default: '20px'
},
/* 区域文本 */
text: {
type: String
},
/* 过渡速度(默认30,值越大速度越快) */
speed: {
type: Number,
default: 30
},
/* 是否默认滚动(默认否) */
isDefaultRoll: {
type: Boolean,
default: false
}
})
const noticeSpanStyle = ref({})
const noticeRef = ref<HTMLElement>()
const noticeDivRef = ref<HTMLElement>()
const noticeStyle = computed<{}>(() => {
return {
width: props.w,
'white-space': 'nowrap',
overflow: 'hidden',
position: 'relative',
height: props.h
}
})
onMounted(() => {
noticeSpanStyle.value = {
left: `100%`,
transition: '0s'
}
})
const setAni = (width) => {
const delay = width / props.speed
noticeSpanStyle.value = {
left: `-${width}px`,
transition: `${delay}s linear`
}
setTimeout(() => {
noticeSpanStyle.value = {
left: `100%`,
transition: `0s linear`
}
nextTick(() => {
setAni(noticeRef.value?.offsetWidth)
})
}, delay * 1000)
}
watch(
() => props.text,
() => {
nextTick(() => {
let spanW = noticeRef.value?.offsetWidth || 0
let divW = noticeDivRef.value?.offsetWidth || 0
if (spanW <= divW && !props.isDefaultRoll) {
noticeSpanStyle.value = {
left: `0px`,
transition: '0s'
}
return
}
setAni(spanW)
})
}
)
</script>
<style scoped>
.notice-span {
position: absolute;
}
</style>
2. 使用
<script setup lang="ts">
import { ref } from 'vue'
import RegionRoll from '@/components/RegionRoll.vue'
const noticeText = ref('我是文本-我是文本-我是文本-我是文本-我是文本-我是文本-我是文本')
</script>
<template>
<RegionRoll w="100%" :text="noticeText" />
</template>