vue3 高性能无缝滚动插件的实现

1,732 阅读3分钟

起因

vue3大屏开发过程中,列表长度不定,需要做在滚动显示的设计,于是乎在npmjs上找到了下载量超高的无缝滚动的插件,集成简单快捷,体验也很好,不得不说是一个非常优秀的插件,但其有一个致命的缺陷,就是性能问题,当单个基于element-ui编写的组件使用该插件,cpu增加30%左右,当超过4个组件使用,cpu会飙升至120%左右,后期稳定在107~154%之间(chrome使用shift+esc键可打开监控,查看资源占用情况),此刻配置差一点的机器是无法正常工作的,无奈之下只能选择自己造轮子了。

演示地址

fanqie.github.io/tank-vue3-s…

项目中使用

目前该组件已经发布至npmjs仓库,进行了多次补丁升级,欢迎大家使用

安装

npm install --save tank-vue3-seamless-scroll

导入

import TankSeamlessScroll from "tank-vue3-seamless-scroll"

使用组件


<div style="height:300px;">
    <tank-seamless-scroll :step-length="25" :debug="true" :reverse="false">
        <div class="demo">
            <div v-for="i in 2" :key="i">测试{{ i }}</div>
        </div>
    </tank-seamless-scroll>
</div>

git 仓库

github.com/fanqie/tank…

效果展示

造轮子的过程

渲染问题

首先我们要考虑基于fps帧渲染的,那么我们必定会优先考虑 requestAnimationFrame 对象,为快速解决问题,我们使用了d3-timer 插件,默认帧率限制在了(1000/32)ms,也就是32帧。

性能

偏移量更新采用了js设置 css3 3d 模式,保证了性能可利用

ref_warp.value.style.setProperty("transform", `translate3d(0px ,${translateY}px,0px)`)

显示分析

有限复制

复制的目的是为解决连续滚动时,当超出当前容器,继续可视连续的滚动画面,这就预示着我们至少需要×3容器容纳倍数的内容,才能实现无缝滚动,为了提高性能,最后决定最多把这个数字限定为3,考虑到内容高度有可能小于或大于容器高度,所以引出了以下公式:

  • 复制总量 = 向上四舍五入(容器高度/ 内容高度) ×3 PS:
  • 越小的内容复制数量越多,越大的内容填充数量越少,目的只是为了避免视觉白屏的闪烁
  • 无限复制会降低开发难度,但是vue组件无限复制性能问题无法解决,dom复制,无法继承源内容的事件熟悉

限定位Y

当画面滚动到第三页时,若继续滚动,则画面会出现空白内容,因为没有第四页了,所以我们要把第二页的最后一个内容底坐标作为限定位Y,可理解为最终一直循环播放第一页2th内容块到第三页倒数第二个内容块之间内容,但用户是无感知的。

位置计算公式

如果Y轴偏移量大于限定位Y 则需要重新恢复到首个内容块 + 取偏移余Y的位置,进行循环滚动 偏移Y = 偏移Y<限定位Y?符号*(绝对值(偏移Y%内容高度)+内容高度):偏移Y

补充

  • 插件增加了debug模式,开启后会实时显示帧率、偏移量、复制总量
  • 插件增加了反向滚动模式,需要开启 reverse 模式
  • 插件增加了滚动步长速度控制,需要配置 step-length ,该属性值 代表:Y轴偏移量 (像素/秒)