前言
有一个无缝轮播+滚轮控制
的需求,找了很多的方法发现都没办法完美的实现这种效果。
用原生的js实现不是无缝滚动
用无缝滚动插件实现,发现pc端无法实现滚轮控制
目标
1 实现表格表无缝循环滚动 2 实现滚轮控制表格表数据滚动 3 掌握vue-seamless-scroll使用方式
一些思考
如何去完美的实现无缝轮播+滚轮控制
效果呢?,查询了很多资料都没有很完美的兼容两者优点的解决方法。推荐最多的方式就是以下两个:
写JS实现,但实现的思路无外乎用定时+scrollTop
去实现(若有其他的方案,欢迎留言),这种scrollTop方式必然导致闪动,不是无缝的。
第三方组件vue-seamless-scroll
可以完美的实现无缝自动滚动,但是pc端却也无法通过滚轮去控制滚动。
vue-seamless-scroll
无缝滚动的很完美,我就在想能不能试着改动或者操作vue-seamless-scroll
组件去实现滚轮控制呢。于是开始了以下的尝试
前期工作
1 安装
npm install vue-seamless-scroll --save
2 引入并注册
import VueSeamlessScroll from "vue-seamless-scroll";
export default {
name: "SeamleScroll",
components: {
VueSeamlessScroll,
},
}
3 使用组件
<vue-seamless-scroll ref="seamleScroll" class="seamlessScroll" :data="tableData" :class-option="scrollOptions">
// 要滚动的内容
</vue-seamless-scroll>
在开始之前,先看一下这个第三方组件有哪些参数或者属性
官方文档:vue-seamless-scroll configure
key | 描述 | 默认值 | 类型 |
---|---|---|---|
step | 滚动速度 | 1 | Number |
limitMoveNum | 开始无缝滚动的最小数据量 | 5 | Number |
hoverStop | 是否开启鼠标悬停stop | true | Boolean |
direction | 方向:0向下 1向上 2向左 3向右 | 1 | Number |
openTouch | 是否开启移动端触屏 | true | Boolean |
waitTime | 单步运动停止的时间(默认值1000ms) | 1000 | Boolean |
基本属性配置
data() {
return {
scrollOptions:{
step: 1,
limitMoveNum: 2, // 开始无缝滚动的最小数据量
hoverStop: true, // 是否开启鼠标悬停stop
openTouch: true,
direction: 1, // 0向下 1向上 2向左 3向右
openWatch: true, // 开启数据实时监控刷新dom
singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
waitTime: 1000, // 单步运动停止的时间(默认值1000ms)
}
};
},
将基本配置scrollOptions传递给第三方组件vue-seamless-scroll
<vue-seamless-scroll :data="tableData" :class-option="scrollOptions">
// 要滚动的内容
</vue-seamless-scroll>
这样就能在页面上看到vue-seamless-scroll的无缝滚动效果
表格列滚动效果实现
这里用的是el-table
表格组件。
若直接将el-table表格插入到vue-seamless-scroll组件中,会导致el-table表格中的表头也会进行滚动,这不是想要的效果。
这里用两个el-table,一个保留表头部分,一个保留内容部分。保留内容部分的放入vue-seamless-scroll组件中进行无缝滚动
<!--第一个表格,保留表头部分-->
<el-table class="table" :data="tableData">
<el-table-column prop="id" label="ID" width="180"></el-table-column>
<el-table-column
prop="index"
label="序号"
width="180"
></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
</el-table>
<!--无缝滚动,表格列表内容-->
<vue-seamless-scroll ref="seamleScroll"
class="seamlessScroll"
:data="tableData"
:class-option="scrollOptions"
>
<!--第二个表格,保留列表内容部分-->
<el-table class="scroll-content" :data="tableData">
<el-table-column prop="id" label="ID" width="180"></el-table-column>
<el-table-column
prop="index"
label="序号"
width="180"
></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
</el-table>
</vue-seamless-scroll>
样式
/* 隐藏内容 */
.table .el-table__body-wrapper {
display: none;
}
/* 隐藏表头 */
.scroll-content .el-table__header {
display: none;
}
这样就能实现列表内容的滚动了
将需求细分为如下: 1 滚轮控制滚动方向和速度,滚轮停止滚动也停止 2 鼠标移入暂停,鼠标移出回复默认的滚动效果
滚轮控制
监听滚轮滚动事件,根据滚轮的方向控制滚动动画的方向和速度
在进入页面时候,添加滚轮监听
事件,
并将滚动的初始方向与速度记录下来以方便滚轮滚动结束之后,恢复到原始效果.
mounted() {
let arr = []
for(let i=0;i<20;i++){
arr.push({
id: Date.now(),
index: i+1,
address: "上海市普陀区金沙江路 1518 弄",
})
}
this.tableData = arr // 数据
// 初始化滚轮速度与方向
this.direction = 1 // 默认向下滚动
this.initOption = {
step: this.scrollSpeed,
direction: this.direction, // 0向下 1向上 2向左 3向右
}
// 监听滚轮滚动
const scrollContainer = this.$el.querySelector(".seamlessScroll");
scrollContainer.addEventListener("wheel", this.handleWheel);
},
滚轮滚动事件 1 判断数据长度是否满足滚动
handleWheel(event) {
// 有数据且数据长度大于无缝滚动的最小数据量,才允许滚轮生效
if(this.tableData.length&&this.tableData.length>this.scrollOptions.limitMoveNum){
// 滚动逻辑处理
}
},
2 滚动逻辑处理
根据滚轮事件传递的参数event
,改变滚轮方向和速度
改完之后发现==滚动还是暂停的==,这是因为在对vue-seamless-scroll基本属性进行配置的时候,
开启了鼠标悬浮暂停
,在进行滚轮滚动的之前动画已暂停
// 判断滚轮方向
const delta = event.deltaY > 0 ? 1 : 0;
this.scrollSpeed = 5; // 默认滚轮速度
this.direction = delta // 滚轮方向
因此 修改完基本配置后,还需要去启动滚动动画
leave()
方法是vue-seamless-scroll提供的
有兴趣的可以下载下来看一下vue-seamless-scroll组件的源码。
// 滚动
this.$refs.seamleScroll.leave()
若到此就结束,会导致你滚动了一下,往后的滚动动画都按照你此次滚动进行,再进行滚动也没有效果了 为此加了一个定时关闭的事件 去暂停滚轮滚动,这样就会有滚轮控制的感觉
setTimeout(() => {
// 暂停滚动
!this.isLeave ? this.$refs.seamleScroll._cancle() : ''
}, 800);
滚动事件完整代码
handleWheel(event) {
// 有数据且数据长度大于无缝滚动的最小数据量,才允许滚轮生效
if(this.tableData.length&&this.tableData.length>this.scrollOptions.limitMoveNum){
// 判断滚轮方向
const delta = event.deltaY > 0 ? 1 : 0;
this.scrollSpeed = 5; // 默认滚轮速度
this.direction = delta // 滚轮方向
// 滚动
this.$refs.seamleScroll.leave()
setTimeout(() => {
// 当鼠标未移出时暂停滚动
!this.isLeave ? this.$refs.seamleScroll._cancle() : ''
}, 800);
}
},
vue-seamless-scroll
源码中触发滚动的方法leave()
与_move()
leave()
鼠标移开时触发滚动(底层还是调用的_move()
方法)
_move()
启动滚动
为什么滚轮事件中,启动滚动用leave()
方法,这是因为鼠标移入会设置isHover为true,关闭_move()方法
鼠标移入暂停,移出恢复默认
鼠标移入暂停,vue-seamless-scroll组件支持此效果,只需要再基本属性进行配置的时候hoverStop
设置为true
鼠标移入事件
handleMouseEnter() {
// 鼠标移入,滚轮停止时,暂停滚动
this.isLeave = false
}
鼠标离开事件
handleMouseLeave(){
// 鼠标移除,继续滚动
if(this.tableData.length<1||this.tableData.length<=this.scrollOptions.limitMoveNum) return
this.isLeave = true // 是否离开 true离开
this.direction = 1 // 恢复默认滚动
this.scrollSpeed = this.initOption.step ? this.initOption.step || 1 : 0
this.$refs.seamleScroll._move()
}
最终的效果
总结
1 js去写滚动事件会有闪动 2 第三方组件vue-seamless-scroll本身是不支持pc端滚轮控制的,通过滚轮来操作vue-seamless-scroll组件中的配置与方法来实现,当然这种也不是100%灵活的
若有其他更完美的方法,欢迎评论.............