赞
踩
可自定义设置以下属性:
滚动文字数组(sliderText),类型:Array<{title: string, link?: string}>,必传,默认[]
滚动区域宽度(width),类型:number | string,默认 ‘100%’
滚动区域高度(height),类型:number,单位px,默认 60
滚动区域背景色(backgroundColor),类型:string,默认 ‘#FFF’
滚动区域展示条数,水平滚动时生效(amount),类型:number,默认 4
水平滚动文字各列间距或垂直滚动文字两边的边距(gap),类型:number,单位px,默认 20
是否垂直滚动(vertical),类型:boolean,默认 false
文字滚动时间间隔,垂直滚动时生效(interval),类型:number,单位ms,默认 3000
详见:描述
1:创建文字滚动组件TextScroll.vue:
<script setup lang="ts"> import { ref, computed, onMounted } from 'vue' import { requestAnimationFrame, cancelAnimationFrame, rafTimeout, cancelRaf } from '../index' interface Text { title: string // 文字标题 link?: string // 跳转链接 } interface Props { sliderText: Text[] // 滚动文字数组 width?: number|string // 滚动区域宽度,单位px height?: number // 滚动区域高度,单位px backgroundColor?: string // 滚动区域背景色 amount?: number // 滚动区域展示条数,水平滚动时生效 gap?: number // 水平滚动文字各列间距或垂直滚动文字两边的边距,单位px vertical?: boolean // 是否垂直滚动 interval?: number // 文字滚动时间间隔,单位ms,垂直滚动时生效 } const props = withDefaults(defineProps<Props>(), { sliderText: () => [], width: '100%', height: 60, backgroundColor: '#FFF', amount: 4, gap: 20, vertical: false, interval: 3000, }) // horizon const left = ref(0) const fpsRaf = ref(0) // fps回调标识 const moveRaf = ref() // 一个 long 整数,请求 ID ,是回调列表中唯一的标识。是个非零值,没别的意义 const fps = ref(60) const textData = ref<Text[]>([...props.sliderText]) const horizonRef = ref() const distance = ref(0) // 每条滚动文字移动距离 const step = computed(() => { // 移动参数(120fps: 0.5, 60fps: 1) if (fps.value === 60) { return 1 } else { return 60 / fps.value } }) function getFPS () { // 获取屏幕刷新率 // @ts-ignore const requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame var start: any = null function timeElapse (timestamp: number) { /* timestamp参数:与performance.now()的返回值相同,它表示requestAnimationFrame() 开始去执行回调函数的时刻 */ if (!start) { if (fpsRaf.value > 10) { start = timestamp } fpsRaf.value = requestAnimationFrame(timeElapse) } else { fps.value = Math.floor(1000 / (timestamp - start)) console.log('fps', fps.value) distance.value = getDistance() // 获取每列文字宽度 onStart() // 开始滚动 } } fpsRaf.value = requestAnimationFrame(timeElapse) } function getDistance ():number { return parseFloat((horizonRef.value.offsetWidth / props.amount).toFixed(2)) } function moveLeft () { if (left.value >= distance.value) { textData.value.push(textData.value.shift() as Text) // 将第一条数据放到最后 left.value = 0 } else { left.value += step.value // 每次移动step(px) } moveRaf.value = requestAnimationFrame(moveLeft) } const totalWidth = computed(() => { // 文字滚动区域总宽度 if (typeof props.width === 'number') { return props.width + 'px' } else { return props.width } }) const len = computed(() => { return props.sliderText.length }) onMounted(() => { if (props.vertical) { onStart() // 启动垂直滚动 } else { getFPS() } }) function onStart () { if (props.vertical) { if (len.value > 1) { startMove() // 开始滚动 } } else { if (textData.value.length > props.amount) { // 超过amount条开始滚动 moveRaf.value = requestAnimationFrame(moveLeft) // 开始动画 } } } function onStop () { if (props.vertical) { if (len.value > 1) { cancelRaf(timer) } } else { cancelAnimationFrame(moveRaf.value) // 暂停动画 } } const emit = defineEmits(['click']) function onClick (title: string) { // 通知父组件点击的标题 emit('click', title) } // vertical const actIndex = ref(0) var timer: any = null function startMove () { timer = rafTimeout(() => { if (actIndex.value === len.value - 1) { actIndex.value = 0 } else { actIndex.value++ } startMove() }, props.interval) } </script> <template> <div v-if="!vertical" class="m-slider-horizon" @mouseenter="onStop" @mouseleave="onStart" ref="horizonRef" :style="`height: ${height}px; width: ${totalWidth}; background: ${backgroundColor};`"> <a :style="`will-change: transform; transform: translateX(${-left}px); width: ${distance - gap}px; margin-left: ${gap}px;`" class="u-slide-title" v-for="(text, index) in textData" :key="index" :title="text.title" :href="text.link ? text.link:'javascript:;'" :target="text.link ? '_blank':'_self'" @click="onClick(text.title)"> {{ text.title || '--' }} </a> </div> <div v-else class="m-slider-vertical" @mouseenter="onStop" @mouseleave="onStart" :style="`height: ${height}px; width: ${totalWidth}; background: ${backgroundColor};`"> <TransitionGroup name="slide"> <div class="m-slider" :style="`width: calc(${totalWidth} - ${2*gap}px); height: ${height}px;`" v-for="(text, index) in sliderText" :key="index" v-show="actIndex===index"> <a class="u-slider" :title="text.title" :href="text.link ? text.link:'javascript:;'" :target="text.link ? '_blank':'_self'" @click="onClick(text.title)"> {{ text.title }} </a> </div> </TransitionGroup> </div> </template> <style lang="less" scoped> // 水平滚动 .m-slider-horizon { box-shadow: 0px 0px 5px #D3D3D3; border-radius: 6px; white-space: nowrap; overflow: hidden; text-align: center; // 水平居中 &:after { // 垂直居中 content: ''; height: 100%; display: inline-block; vertical-align: middle; } .u-slide-title { display: inline-block; vertical-align: middle; font-size: 16px; color: #333; font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; &:hover { color: @themeColor; } } } // 垂直滚动 .slide-enter-active, .slide-leave-active { transition: all 1s ease; } .slide-enter-from { transform: translateY(50px) scale(0.6); opacity: 0; } .slide-leave-to { transform: translateY(-50px) scale(0.6); opacity: 0; } .m-slider-vertical { position: relative; overflow: hidden; border-radius: 6px; .m-slider { position: absolute; left: 0; right: 0; margin: 0 auto; text-align: center; // 水平居中 &:after { // 垂直居中 content: ''; height: 100%; display: inline-block; vertical-align: middle; } .u-slider { max-width: 100%; display: inline-block; vertical-align: middle; font-size: 18px; line-height: 28px; color: #333; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor: pointer; &:hover { color: @themeColor; } } } } </style>
2:在要使用的页面引入:
<script setup lang="ts"> import TextScroll from './TextScroll.vue' import { ref } from 'vue' const sliderText = ref([ { title: '美国作家杰罗姆·大卫·塞林格创作的唯一一部长篇小说', link: 'https://www.baidu.com' }, { title: '首次出版于1951年' }, { title: '塞林格将故事的起止局限于16岁的中学生霍尔顿·考尔菲德从离开学校到纽约游荡的三天时间内,塞林格将故事的起止局限于16岁的中学生霍尔顿·考尔菲德从离开学校到纽约游荡的三天时间内' }, { title: '并借鉴了意识流天马行空的写作方法,充分探索了一个十几岁少年的内心世界' }, { title: '愤怒与焦虑是此书的两大主题,主人公的经历和思想在青少年中引起强烈共鸣' } ]) function onClick (value: string) { // 获取点击的标题 console.log('value:', value) } </script> <template> <div> <h2 class="mb10">TextScroll 横向文字滚动基本使用</h2> <TextScroll :sliderText="sliderText" @click="onClick" width="100%" :amount="4" backgroundColor="#FFF" :height="50" /> <h2 class="mt30 mb10">垂直文字滚动基本使用 (vertical)</h2> <TextScroll :sliderText="sliderText" @click="onClick" vertical backgroundColor="#e6f4ff" :gap="60" :interval="3000" width="100%" :height="60" /> </div> </template> <style lang="less" scoped> </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。