前言
有一个无缝轮播+滚轮控制的需求,找了很多的方法发现都没办法完美的实现这种效果。
用原生的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,
  },
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

3 使用组件

<vue-seamless-scroll ref="seamleScroll" class="seamlessScroll" :data="tableData" :class-option="scrollOptions">
// 要滚动的内容
</vue-seamless-scroll>
  • 1.
  • 2.
  • 3.

在开始之前,先看一下这个第三方组件有哪些参数或者属性

官方文档: vue-seamless-scroll
configure

key描述默认值类型
step滚动速度1Number
limitMoveNum开始无缝滚动的最小数据量5Number
hoverStop是否开启鼠标悬停stoptrueBoolean
direction方向:0向下 1向上 2向左 3向右1Number
openTouch是否开启移动端触屏trueBoolean
waitTime单步运动停止的时间(默认值1000ms)1000Boolean

基本属性配置

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)
      }
    };
  },
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

将基本配置scrollOptions传递给第三方组件vue-seamless-scroll

<vue-seamless-scroll :data="tableData" :class-option="scrollOptions">
// 要滚动的内容
</vue-seamless-scroll>
  • 1.
  • 2.
  • 3.

这样就能在页面上看到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>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

样式

/* 隐藏内容 */
.table .el-table__body-wrapper {
  display: none;
}
/* 隐藏表头 */
.scroll-content .el-table__header {
  display: none;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

这样就能实现列表内容的滚动了【vue】实现自动轮播+滚轮控制_默认值

将需求细分为如下:
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.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

滚轮滚动事件
1 判断数据长度是否满足滚动

handleWheel(event) {
   // 有数据且数据长度大于无缝滚动的最小数据量,才允许滚轮生效
  if(this.tableData.length&&this.tableData.length>this.scrollOptions.limitMoveNum){
    // 滚动逻辑处理
  }
},
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

2 滚动逻辑处理
根据滚轮事件传递的参数event,改变滚轮方向和速度

改完之后发现滚动还是暂停的,这是因为在对vue-seamless-scroll基本属性进行配置的时候,
开启了鼠标悬浮暂停,在进行滚轮滚动的之前动画已暂停

// 判断滚轮方向
const delta = event.deltaY > 0 ? 1 : 0;
this.scrollSpeed = 5; // 默认滚轮速度
this.direction = delta // 滚轮方向
  • 1.
  • 2.
  • 3.
  • 4.

因此 修改完基本配置后,还需要去启动滚动动画leave()方法是vue-seamless-scroll提供的
有兴趣的可以下载下来看一下 vue-seamless-scroll组件的源码。

// 滚动
this.$refs.seamleScroll.leave()
  • 1.
  • 2.

若到此就结束,会导致你滚动了一下,往后的滚动动画都按照你此次滚动进行,再进行滚动也没有效果了
为此加了一个定时关闭的事件 去暂停滚轮滚动,这样就会有滚轮控制的感觉

setTimeout(() => {
  // 暂停滚动
  !this.isLeave ? this.$refs.seamleScroll._cancle() : ''
}, 800);
  • 1.
  • 2.
  • 3.
  • 4.

滚动事件完整代码

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);
      }
    },
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

vue-seamless-scroll源码中触发滚动的方法leave()_move()leave() 鼠标移开时触发滚动(底层还是调用的_move() 方法)_move() 启动滚动

为什么滚轮事件中,启动滚动用leave()方法,这是因为鼠标移入会设置isHover为true,关闭_move()方法【vue】实现自动轮播+滚轮控制_无缝滚动_02

鼠标移入暂停,移出恢复默认

鼠标移入暂停,vue-seamless-scroll组件支持此效果,只需要再基本属性进行配置的时候hoverStop设置为true鼠标移入事件

handleMouseEnter() {
  // 鼠标移入,滚轮停止时,暂停滚动
  this.isLeave = false
}
  • 1.
  • 2.
  • 3.
  • 4.

鼠标离开事件

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.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

最终的效果【vue】实现自动轮播+滚轮控制_默认值_03

总结

1 js去写滚动事件会有闪动
2 第三方组件vue-seamless-scroll本身是不支持pc端滚轮控制的,通过滚轮来操作vue-seamless-scroll组件中的配置与方法来实现,当然这种也不是100%灵活的

若有其他更完美的方法,欢迎评论…