Vue3 实现一个无缝滚动组件(支持鼠标手动滚动)

2023-09-15 10:38:20

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滚动的方向stringtop ,bottom,left,right
isRoller是否可以使用滚轮滚动booleantrue,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地址:https://gitee.com/fcli/vue-auto-scroll.git

更多推荐

干货!网络丢包故障定位全景指南

极客星球:深入理解网络子系统欢迎加入极客星球,一起学习,快速成长:修炼基本功,打好高薪基础:分享基础技术深度理解,基础概念深度解析,经典书籍推荐和读书分享,经典源码阅读分享等,不定期直播分享,问题答疑解惑;扩展技术深度和技术视野:分享热门技术发展,国内外大厂技术内幕,业界解决方案;校招/社招免费就业指导:模拟面试,简历

精准测试(针对人工执行的测试用例和自动化测试脚本)

在软件测试中,我们常常碰到两个基本问题(困难):很难保障无漏测:我们做了大量测试,但不清楚测得怎样,对软件上线后会不会出问题,没有信心;选择待执行的测试用例:面对大量的回归测试用例时,我们没有足够的时间完成测试,如何选择出有效的测试用例呢?虽然我们会有一些策略,如基于风险的测试策略、基于操作剖面的测试策略或组合测试策略

系统架构:软件工程速成

文章目录参考概述软件工程概述软件过程可行性分析可行性分析概述数据流图数据字典需求分析需求分析概述ER图状态转换图参考软件工程速成(期末+考研复试+软考)均适用.支持4K概述软件工程概述定义:采用工程的概念、原理、技术和方法来开发与维护软件。三要素:方法:完成软件开发各项任务的技术方法,回答“怎么做”。工具:为运用方法提

美创科技入选IDC中国等保合规市场报告推荐厂商

近日,全球领先的IT研究和咨询公司IDC正式发布《IDCPersepctive:中国等保合规市场洞察,2023》报告。在该市场报告中,IDC对中国等保合规市场的发展现状进行调研,明确了最终用户等保合规建设的痛点、难点,阐述了市场中各技术服务提供商的产品服务方案和优势。美创科技凭借在数据安全和运行安全领域专业能力与积累实

垃圾收集算法

1.如何判断对象是否存活?1.1引用计数算法基本思路:在对象中添加一个引用计数器每当有一个地方引用它的时候,计数器就加+1每当有一个引用失效的时候,计数器就减-1当计数器的值为0的时候,那么该对象就是可被GC回收的垃圾对象存在的问题:对象循环引用a对象引用了b对象,b对象也引用了a对象,a、b对象却没有再被其他对象所引

单片机外设-串口(UART)详情

目录学习UART要先认识一些基础知识一:什么是串行、并行通信?(1)串行通信串行通信概念:串行通信的特点:(2)并行通信并行通信概念:并行通信特点:二:什么是异步通信、同步通信?(1)异步通信​编辑异步通信概念:异步通信特点:(2)同步通信同步通信概念:1、外同步2、自同步同步通信特点:三:什么是单工、半双工、全双工通

Vue知识系列(5)每天10个小知识点

目录系列文章目录Vue知识系列(1)每天10个小知识点Vue知识系列(2)每天10个小知识点Vue知识系列(3)每天10个小知识点Vue知识系列(4)每天10个小知识点知识点41.vue常用基本指令有哪些以及他们的作用和使用场景42.Vue组件中data为什么必须是函数43.v-if和v-show的区别44.vue自定

Git(7)——使用Beyond Compare快速解决冲突

一、简介根据前六章的学习,我们应该很清楚地感知到不同分支合并代码时产生的冲突是最让我们头疼的问题,因为他需要我们手动去解决冲突的文件,有没有一种方法可以快速地解决冲突呢?本篇文章将介绍如何使用ByondCompare去快速解决冲突二、在Git中进行配置使用如下命令对Git进行配置注:这里的--local是指以下这命令配

Nacos内核设计之一致性协议(上)

Nacos一致性协议Nacos技术架构先简单介绍下Nacos的技术架构从而对nacos有一个整体的认识如图Nacos架构分为四层用户层、应用层、核心层、各种插件再深入分析下nacos一致性协议的发展过程及原理实现为什么nacos需要一致性协议Nacos是一个需要存储数据的一个组件为了实现这个目标,就需要在Nacos内部

(2022,DALL·E2,CLIP,Diffusion,AR)使用 CLIP 潜在空间的分层文本条件图像生成

HierarchicalText-ConditionalImageGenerationwithCLIPLatents公众号:EDPJ(添加VX:CV_EDPJ或直接进Q交流群:922230617获取资料)目录0.摘要1.简介2.方法2.1解码器2.2先验3.图像处理3.1变化3.2插值3.3文本差异(TextDiffs

stm32学习笔记:OLED显示屏

一、OLED简介OLED:有机发光二极管,供电∶3~5.5V,通信协议︰I2C/SPI,分辨率∶128+64二、常用的调试方式串口调试∶通过串口通信,将调试信息发送到电脑端,电脑使用串口助手显示调试信息显示屏调试∶直接将显示屏连接到单片机,将调试信息打印在显示屏上Keil调试模式∶借助Keil软件的调试模式,可使用单步

热文推荐