百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

svelte组件系列:svelte3自定义虚拟滚动条SvelteScrollbar

sinye56 2024-10-22 16:30 11 浏览 0 评论

最近一直在捣鼓svelte.js框架。今天给大家分享一个svelte3自定义美化虚拟滚动条组件svelteScrollbar。

svelte-scorllbar滚动条组件 支持原生滚动条、自动隐藏、水平+垂直滚动(滚轮滑动)、自定义滚动条大小、背景色、间距及动态实时更新等功能。

功能及效果有些和el-scrollbar组件类似。

引入组件

import Scrollbar from '$lib/Scrollbar'

使用组件

使用<Scrollbar></Scrollbar>包裹的区域即可快速生成一个虚拟化滚动条组件。

<!-- //原生滚动条 -->
<Scrollbar native>
    <div>自定义内容信息。</div>
</Scrollbar>

<!-- //自动隐藏滚动条 -->
<Scrollbar autohide={true}>
    <div>自定义内容信息。</div>
</Scrollbar>

<!-- //水平滚动条(支持滚轮滑动) -->
<Scrollbar mousewheel>
    <div>自定义内容信息。</div>
</Scrollbar>

<!-- //自定义高度/最大高度 -->
<Scrollbar height="200" maxHeight="350">
    <div>自定义内容信息。</div>
</Scrollbar>

<!-- //自定义大小/间隙/颜色 -->
<Scrollbar size="10px" gap="5" color="#09f">
    <div>自定义内容信息。</div>
</Scrollbar>

svelte-scrollbar配置参数

支持如下参数配置。

<script>
    // 是否开启原生滚动条
    export let native = false
    // 是否自动隐藏滚动条
    export let autohide = false
    // 滚动条尺寸
    export let size = undefined
    // 滚动条颜色
    export let color = ''
    // 滚动条层叠
    export let zIndex = null
    // 滚动条区域高度
    export let height = undefined
    // 滚动条区域最大高度
    export let maxHeight = undefined
    // 滚动条间隙
    export let gap = 0
    // 是否开启水平滚轮滚动控制
    export let mousewheel = false
    
    ...
</script>

组件模板

<div class="vui__scrollbar" bind:this={el} on:mouseenter={handleMouseEnter} on:mouseleave={handleMouseLeave}>
    <div class="vscroll__wrap" class:hidenative={!bool(native)} bind:this={wrap} on:scroll={handleScroll} on:mousewheel={handleMouseWheel} style="{wrapStyle}">
        <slot />
    </div>
    <div class="vscroll__bar vertical" class:ishide={!data.isShowBar} on:mousedown={e => handleClickTrack(e, 0)} >
        <div class="vscroll__thumb" bind:this={barY} style="background: {color}; height: {data.barHeight}px; width: {addUnit(size)}" on:mousedown={e => handleDragThumb(e, 0)}></div>
    </div>
    <div class="vscroll__bar horizontal" class:ishide={!data.isShowBar} on:mousedown={e => handleClickTrack(e, 1)}>
        <div class="vscroll__thumb" bind:this={barX} style="background: {color}; width: {data.barWidth}px; height: {addUnit(size)}" on:mousedown={e => handleDragThumb(e, 1)}></div>
    </div>
</div>

js逻辑处理

<script>
    /**
     * @Desc     svelte3.x桌面端虚拟滚动条组件SvelteScrollbar
     */
     
    // ...

    import { onMount, afterUpdate, createEventDispatcher, tick } from 'svelte'
    const dispatch = createEventDispatcher()

    import util from './util'

    $: data = {
        // 滚动条宽度
        barWidth: 0,
        // 滚动条高度
        barHeight: 0,
        // 滚动条水平偏移率
        ratioX: 1,
        // 滚动条垂直偏移率
        ratioY: 1,
        // 鼠标是否按住滚动条
        isTaped: false,
        // 鼠标是否悬停于滚动区域
        isHover: false,
        // 显示滚动条
        isShowBar: !bool(autohide)
    }

    const bool = (boolean) => JSON.parse(boolean) ? true : false
    const addUnit = (val) => val ? parseInt(val) + 'px' : null

    let observeTimer = null
    let c = {}
    // 滚动条对象
    let el
    let wrap
    let barX
    let barY

    $: wrapStyle = `height: ${addUnit(height)}; max-height: ${addUnit(maxHeight)}`
    $: GAP = addUnit(gap)

    onMount(() => {
        console.log('监听滚动条开启...')

        updated()

        let observer = new MutationObserver(mutation => {
            updated()
        })

        observer.observe(wrap, {
            attributes: true,
            childList: true,
            subtree: true,
            attributeFilter: [
                'style', 'class'
            ]
        })

        window.addEventListener('resize', util.throttle(updated))

        return () => {
            observer.disconnect()
            window.removeEventListener('resize', updated)
            console.log('监听滚动条关闭...')
        }
    })

    afterUpdate(() => {
        // console.log('监听dom更新...')
    })

    // 鼠标滑入
    function handleMouseEnter() {
        data.isHover = true
        data.isShowBar = true
        updated()
    }

    // 鼠标滑出
    function handleMouseLeave() {
        data.isHover = false
        if(!data.isTaped && bool(autohide)) {
            data.isShowBar = false
        }
    }

    // 拖动滚动条
    function handleDragThumb(e, index) {
        // ...
    }

    // 点击滚动条插槽
    function handleClickTrack(e, index) {
        if(index == 0) {
            wrap.scrollTop = (Math.abs(e.target.getBoundingClientRect().top - e.clientY) - barY.offsetHeight / 2) * data.ratioY
            barY.style.transform = `translateY(${wrap.scrollTop / data.ratioY}px)`
        }else {
            wrap.scrollLeft = (Math.abs(e.target.getBoundingClientRect().left - e.clientX) - barX.offsetWidth / 2) * data.ratioX
            barX.style.transform = `translateX(${wrap.scrollLeft / data.ratioX}px)`
        }
    }

    // 更新滚动区
    async function updated() {
        // ...
    }

    // 鼠标滚动事件
    function handleScroll(e) {
        let target = e.target
        let status
        if(target.scrollTop == 0) {
            status = 'top' // 滚动至顶部
        }else if(target.scrollTop + target.offsetHeight >= target.scrollHeight) {
            status = 'bottom' // 滚动至底部
        }

        /**
         * 父组件调用 const { target, status, scrollTop, scrollLeft } = e.detail
         */
        dispatch('scroll', {
            target, // 滚动对象
            status, // 滚动状态(记录滚动位置)
            scrollTop: target.scrollTop,
            scrollLeft: target.scrollLeft
        })
        updated()
    }

    // 控制滚轮水平滚动
    function handleMouseWheel(e) {
        if(!bool(mousewheel)) return
        e.preventDefault()
        if(wrap.scrollWidth > wrap.offsetWidth) {
            wrap.scrollLeft += e.deltaY
        }
    }

    // 滚动到一组特定坐标
    export async function scrollTo(arg1, arg2) {
        await tick()

        if(typeof arg1 == 'object') {
            wrap.scrollTo(arg1)
        }else if(!isNaN(arg1) && !isNaN(arg2)) {
            wrap.scrollTo(arg1, arg2)
        }
    }

    // 设置滚动条到顶部的距离
    export async function setScrollTop(value) {
        await tick()

        wrap.scrollTop = value == 'top' ? 0 : value == 'bottom' ? wrap.scrollHeight : parseInt(value)
        barY.style.transform = `translateY(${wrap.scrollTop / data.ratioY}px)`
    }

    // 设置滚动条到左边的距离
    export async function setScrollLeft(value) {
        await tick()

        wrap.scrollLeft = value == 'left' ? 0 : value == 'right' ? wrap.scrollWidth : parseInt(value)
        barX.style.transform = `translateX(${wrap.scrollLeft / data.ratioX}px)`
    }
</script>

如上图:支持滚动到指定位置及监听滚动事件。

好了,基于svelte3自定义滚动条组件就分享到这里。后续还会分享一些svelte实例项目。

相关推荐

程序员:JDK的安装与配置(完整版)_jdk的安装方法

对于Java程序员来说,jdk是必不陌生的一个词。但怎么安装配置jdk,对新手来说确实头疼的一件事情。我这里以jdk10为例,详细的说明讲解了jdk的安装和配置,如果有不明白的小伙伴可以评论区留言哦下...

Linux中安装jdk并配置环境变量_linux jdk安装教程及环境变量配置

一、通过连接工具登录到Linux(我这里使用的Centos7.6版本)服务器连接工具有很多我就不一一介绍了今天使用比较常用的XShell工具登录成功如下:二、上传jdk安装包到Linux服务器jdk...

麒麟系统安装JAVA JDK教程_麒麟系统配置jdk

检查检查系统是否自带java在麒麟系统桌面空白处,右键“在终端打开”,打开shell对话框输入:java–version查看是否自带java及版本如图所示,系统自带OpenJDK,要先卸载自带JDK...

学习笔记-Linux JDK - 安装&amp;配置

前提条件#检查是否存在JDKrpm-qa|grepjava#删除现存JDKyum-yremovejava*安装OracleJDK不分系统#进入安装文件目...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

测试员必备:Linux下安装JDK 1.8你必须知道的那些事

1.简介在Oracle收购Sun后,Java的一系列产品就被整合到Oracle官网中,打开官网乍眼一看也不知道去哪里下载,还得一个一个的摸索尝试,而且网上大多数都是一些Oracle收购Sun前,或者就...

Linux 下安装JDK17_linux 安装jdk1.8 yum

一、安装环境操作系统:JDK版本:17二、安装步骤第一步:下载安装包下载Linux环境下的jdk1.8,请去官网(https://www.oracle.com/java/technologies/do...

在Ubuntu系统中安装JDK 17并配置环境变量教程

在Ubuntu系统上安装JDK17并配置环境变量是Java开发环境搭建的重要步骤。JDK17是Oracle提供的长期支持版本,广泛用于开发Java应用程序。以下是详细的步骤,帮助你在Ubuntu系...

如何在 Linux 上安装 Java_linux安装java的步骤

在桌面上拥抱Java应用程序,然后在所有桌面上运行它们。--SethKenlon(作者)无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序...

Windows和Linux环境下的JDK安装教程

JavaDevelopmentKit(简称JDK),是Java开发的核心工具包,提供了Java应用程序的编译、运行和开发所需的各类工具和类库。它包括了JRE(JavaRuntimeEnviro...

linux安装jdk_linux安装jdk软连接

JDK是啥就不用多介绍了哈,外行的人也不会进来看我的博文。依然记得读大学那会,第一次实验课就是在机房安装jdk,编写HelloWorld程序。时光飞逝啊,一下过了十多年了,挣了不少钱,买了跑车,娶了富...

linux安装jdk,全局配置,不同用户不同jdk

jdk1.8安装包链接:https://pan.baidu.com/s/14qBrh6ZpLK04QS8ogCepwg提取码:09zs上传文件解压tar-zxvfjdk-8u152-linux-...

运维大神教你在linux下安装jdk8_linux安装jdk1.7

1.到官网下载适合自己机器的版本。楼主下载的是jdk-8u66-linux-i586.tar.gzhttp://www.oracle.com/technetwork/java/javase/downl...

window和linux安装JDK1.8_linux 安装jdk1.8.tar

Windows安装JDK1.8的步骤:步骤1:下载JDK打开浏览器,找到JDK下载页面https://d.injdk.cn/download/oraclejdk/8在页面中找到并点击“下载...

最全的linux下安装JavaJDK的教程(图文详解)不会安装你来打我?

默认已经有了linux服务器,且有root账号首先检查一下是否已经安装过java的jdk任意位置输入命令:whichjava像我这个已经安装过了,就会提示在哪个位置,你的肯定是找不到。一般我们在...

取消回复欢迎 发表评论: