前言 有一个无缝轮播+滚轮控制的需求,找了很多的方法发现都没办法完美的实现这种效果。 用原生的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%灵活的

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