vue3实现无缝滚动组件的示例代码
作者:叶落风尘
前言
在日常开发中,经常遇到需要支持列表循环滚动展示,特别是在数据化大屏开发中,无缝滚动使用频率更为频繁,在jquery时代,我们常用的无缝滚动组件为liMarquee,在vue中已经有vue-seamless-scroll组件(通过Vue2实现,不支持鼠标手动滚动),但是在使用过程中,发现滚动后会存在点击事件失效的问题,并且产品提了个需求,需要支持鼠标手动滚动,也要支持自动滚动,于是痛定思痛,决定通过Vue3来实现该功能,该组件已经实现上传npm,可以直接安装使用,链接在文尾。
实现
html部分
首先写一个基础的list结构,通过插槽接收外部传入的list数据,因为需要实现无缝滚动,需要复制出同一份的Dom,在最外层监听鼠标hover和leave的状态,以实现鼠标hover暂停滚动,绑定鼠标滚动事件,在鼠标滚动时记住滚动的位置,在恢复自动滚动时能从当前滚动位置继续滚动。
<div class="custom-list" ref="scrollBody" @mouseenter="mouseenterFunc" @mouseleave="mouseleaveFunc" @mousewheel="mousewheelFunc"> <div class="list-body" :class="{ 'list-body2': isHorizontal }" ref="listBody" :style="{ transform: getScrollDistance() }"> <slot></slot> </div> <div class="list-body" :class="{ 'list-body2': isHorizontal }" ref="tBody" v-if="isCanScroll" :style="{ transform: getScrollDistance() }"> <slot></slot> </div> </div>
实现逻辑
开始
通过父级传入的isHorizontal判断是横向滚动,还是垂直滚动
const start = () => { //判断是否可以滚动函数 let isScrollFunc = (bodySize:number, listSize:number) => { if (bodySize > listSize) { scrollDistance.value = 0; isCanScroll.value = !1; } }; isStop.value = !1; //判断是否可以滚动 if (!isHorizontal.value) { isScrollFunc(bodyHeight.value, listHeight.value); } else { isScrollFunc(bodyWidth.value, listWidth.value); } if (isCanScroll.value) { run(); } }
开始滚动
计算目前滚动的距离,并判断需要滚动的方向,计算下一步滚动的距离。
const run = () => { //清空动画 clearAnimation(); animationFrame.value = window.requestAnimationFrame(() => { //滚动主逻辑函数 let main = (listSize:number, bodySize:number) => { let tempScrollDistance = Math.abs(scrollDistance.value); if (scrollDistance.value < 0) { let cc = 2 * listSize - bodySize; if (tempScrollDistance > cc) { scrollDistance.value = -(listSize - bodySize); } } else { scrollDistance.value = -listSize; } }; //根据滚动方向判断使用高度或宽度控制效果 if (!isHorizontal.value) { main(listHeight.value, bodyHeight.value); } else { main(listWidth.value, bodyWidth.value); } //判断滚动值 if (!isStop.value) { if ( props.scrollDirection === "top" || props.scrollDirection === "left" ) { scrollDistance.value -= props.steep; } else if ( props.scrollDirection === "bottom" || props.scrollDirection === "right" ) { scrollDistance.value += props.steep; } run(); } }); }
获取滚动样式
通过translate实现列表平移,已实现平滑滚动。
const getScrollDistance = () => { let style; if (!isHorizontal.value) { style = "translate(0px, " + scrollDistance.value + "px)"; } else { style = "translate(" + scrollDistance.value + "px,0px)"; } return style; } const clearAnimation = () => { if (animationFrame.value) { cancelAnimationFrame(animationFrame.value); animationFrame.value = null; } }
鼠标滚动
鼠标滚动时实时计算滚动的距离,可通过传入的鼠标滚动速率来计算每次滚动多少。
const mousewheelFunc = (e:any) => { if (!isCanScroll.value || !props.isRoller) { return false; } let dis = e.deltaY; if (dis > 0) { scrollDistance.value -= props.rollerScrollDistance; } else { scrollDistance.value += props.rollerScrollDistance; } run(); }
使用
该组件已上传npm仓库,欢迎satrt使用
npm install @fcli/vue-auto-scroll --save-dev 来安装
在项目中使用
import VueAutoScroll from '@fcli/vue-auto-scroll';
const app=createApp(App)
app.use(VueAutoScroll);
使用示例:
<div class="content"> <vue-auto-scroll :data="list" :steep="0.5" scrollDirection="top" :isRoller="true" :rollerScrollDistance="50"> <div class="li" v-for="i in list" :key="i"> {{ i }} </div> </vue-auto-scroll> </div>
属性 | 属性名称 | 类型 | 可选值 |
---|---|---|---|
steep | 滚动的速率 | number | 为正数即可 |
scrollDirection | 滚动的方向 | string | top ,bottom,left,right |
isRoller | 是否可以使用滚轮滚动 | boolean | true,false |
rollerScrollDistance | 滚轮滚动的速率 | number | (isRoller 必须为 true)为正数即可 |
data | 接收异步数据 | array | 同步任务可不传 |
注: 当scrollDirection 为top或bottom时,一定要为 vue-auto-scroll 组件设置高度。 当scrollDirection 为left或right时,一定要为 vue-auto-scroll 组件设置宽度。并为嵌入vue-auto-scroll中的标签设置样式为display:inline-block; 示例样式名为list-item可以更改为其他类名。当scrollDirection 为left或right时,是基于行内元素的“white-space: nowrap;” 来控制强制不换行的。有可能会影响其内部的文字排列。可以在list-item 层添加 white-space: normal; 来处理给问题。并为其添加固定宽度,以保证文字可以正常换行及插件的正确计算与显示。如果没有为其添加固定宽度,会造成插件获取父容器层的宽度值错误,导致显示混乱
git地址:gitee.com/fcli/vue-auto-scroll
到此这篇关于vue3实现无缝滚动组件的示例代码的文章就介绍到这了,更多相关vue3无缝滚动内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!