一、背景:
<math xmlns="http://www.w3.org/1998/Math/MathML"> 同事忙飞了,叫我帮忙写个大屏列表滚动效果 \color {#000eac} {同事忙飞了,叫我帮忙写个大屏列表滚动效果} </math>同事忙飞了,叫我帮忙写个大屏列表滚动效果 ,正好我也有点空,就去了解下requestAnimationFrame的原理,简单学了下,写了一个案例给他用...
二、直接上完整代码:
js
<template>
<div
ref="scroll"
class="scroll"
@mouseover="handleMouseOver"
@mouseout="handleMouseOut"
>
<div
v-for="item in list"
ref="scrollItem"
:key="item.id"
class="scroll-item"
>
{{ item.title }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [
{
title: "滚动条1",
id: 1
},
{
title: "滚动条2",
id: 2
},
{
title: "滚动条3",
id: 3
},
{
title: "滚动条4",
id: 4
},
{
title: "滚动条5",
id: 5
},
{
title: "滚动条6",
id: 6
},
{
title: "滚动条7",
id: 7
},
{
title: "滚动条8",
id: 8
},
{
title: "滚动条9",
id: 9
},
{
title: "滚动条10",
id: 10
}
// {
// title: "滚动条11",
// id: 11
// },
// {
// title: "滚动条12",
// id: 12
// },
// {
// title: "滚动条13",
// id: 13
// },
// {
// title: "滚动条14",
// id: 14
// }
],
loop: true, // 是否循环滚动
autoplay: true, // 是否开启自动播放
delay: 2000, // 停顿时间
animationId: [], // 动画id列表
isPlay: false // 是否正在播放
}
},
mounted() {
this.init()
},
methods: {
init() {
if (this.autoplay) {
this.scrollStart()
}
},
reInit() {
this.scrollStop()
const scroll = this.$refs.scroll
scroll.scrollTop = 0
this.init()
},
scrollInfo() {
const scroll = this.$refs.scroll
const scrollItem = this.$refs.scrollItem
const scrollHeight = scroll.offsetHeight
const scrollItemHeight = scrollItem[0].offsetHeight
return {
scroll,
scrollHeight,
scrollItemHeight
}
},
scrollStart() {
const { scrollHeight, scrollItemHeight } = this.scrollInfo()
const scrillContentHeight = scrollItemHeight * this.list.length
if (scrillContentHeight < scrollHeight) return
this.isPlay = true
this.scrollEvent()
},
scrollStop() {
this.isPlay = false
this.animationId.map(v => cancelAnimationFrame(v))
},
scrollEvent() {
if ("requestAnimationFrame" in window) {
let id = requestAnimationFrame(this.animationFun)
this.animationId.push(id)
}
},
handleMouseOver() {
this.scrollStop()
},
handleMouseOut() {
this.scrollStart()
},
// 滚动 中间停顿
animationFun(timeStamp, preTimeStamp = 0, diff = 0) {
if (!this.isPlay) return
const { scrollHeight, scrollItemHeight } = this.scrollInfo()
const clientHeight = scrollItemHeight * this.list.length
const scroll = this.$refs.scroll
let currentDiff = timeStamp - preTimeStamp
let n_diff = currentDiff + diff
const stay = scroll.scrollTop % scrollItemHeight == 0
// 中间停顿delay秒
if (stay && n_diff < this.delay) {
let id = requestAnimationFrame(_timeStamp =>
this.animationFun(_timeStamp, timeStamp, n_diff)
)
this.animationId.push(id)
return
}
// 循环滚动
if (stay && this.loop) {
this.loopAnimationFun()
}
if (scrollHeight + scroll.scrollTop < clientHeight) {
scroll.scrollTop =
scroll.scrollTop + this.findMinFactor(scrollItemHeight)
let id = requestAnimationFrame(_timeStamp => {
this.animationFun(_timeStamp, timeStamp, 0)
})
this.animationId.push(id)
}
},
// 循环滚动
loopAnimationFun() {
if (!this.isPlay) return
const scroll = this.$refs.scroll
const { scrollItemHeight } = this.scrollInfo()
const count = Math.floor(scroll.scrollTop / scrollItemHeight)
scroll.scrollTop = Math.floor(scroll.scrollTop / scrollItemHeight) - count
let newList = this.list.splice(0, count)
this.list = this.list.concat(newList)
},
findMaxFactor(num) {
if (num <= 1) return num
for (let i = Math.floor(num / 2); i >= 1; i--) {
if (num % i === 0) {
return i
}
}
return 1
},
findMinFactor(num) {
if (num <= 1) return num
for (let i = 2; i <= Math.floor(num / 2); i++) {
if (num % i === 0) {
return i
}
}
return 1
}
}
}
</script>
<style lang="less" scoped>
.scroll {
margin: 50px auto;
width: 300px;
height: 300px;
overflow-y: hidden;
&-item {
height: 45px;
line-height: 45px;
background-color: #287e35;
cursor: pointer;
}
}
</style>
三、展示效果
四、总结
RequestAnimationFrame
是 JavaScript 的一个高级功能函数,用于优化网页应用的性能和用户体验。以下是它的几个主要优势:
- 减少阻塞 :
RequestAnimationFrame
会暂停当前脚本主线程,让其他操作可以在后台执行,从而避免主线程被卡死或延迟响应。 - 支持 Web Workers 和 JavaScript 组件 :在处理复杂任务(如动画、数据渲染等)时,
RequestAnimationFrame
可以帮助将这些任务分离开到独立的 workers 或渲染队列中,提升整体性能。 - 处理大规模操作 :对于需要频繁更新 UI 的场景(如游戏、大数据可视化或实时数据展示),
RequestAnimationFrame
能够高效地管理动画和渲染流程,避免卡顿。 - 确保及时渲染 :在图形密集的场景中,
RequestAnimationFrame
可以帮助保证每帧动画都能及时渲染,提升用户体验。 - 支持渐变动画 :通过
RequestAnimationFrame
,开发者可以实现更流畅、更复杂的动画效果,尤其是在结合 CSS 动画和 JavaScript 动态更新时。 - 跨浏览器兼容性好 :无论是在 PC、移动端还是其他设备上,
RequestAnimationFrame
都能稳定运行,帮助提升应用的通用性和可靠性。