前段时间有给大家分享两个svelte3.x系列组件。明天持续分享一个最新写的svelte3-scrollbar
虚构丑化零碎滚动条组件。
svelte-layer:一款svelte3.x轻量级PC端弹窗组件
svelte-popup:一款svelte3.x挪动端弹层组件
svelte-scrollbar 一款轻量级网页自定义丑化零碎滚动条组件。反对原生滚动条、自动隐藏、垂直+程度滚动、自定义滚动条大小/色彩/间隙
等性能。
在lib目录下新建一个Scrollbar组件。
引入组件
在须要用到滚动条性能的页面引入插件。
import Scrollbar from '$lib/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><script> /** * @Desc svelte3虚构滚动条组件svelte-scrollbar * @Time andy by 2022-05 * @About Q:282310962 wx:xy190310 */ // ... 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><style> @import 'Scrollbar.scss';</style>
另外还反对动静监听scroll事件。
<Scrollbar on:scroll={handleScroll}> <div>自定义内容信息。</div></Scrollbar><script> // 监听滚动事件 function handleScroll(e) { const { target, status, scrollTop, scrollLeft } = e.detail scrollTopVal = scrollTop scrollLeftVal = scrollLeft // 判断滚动状态(办法1) /*if(scrollTop == 0) { scrollStatus = '滚动至顶部' }else if(scrollTop + target.offsetHeight >= target.scrollHeight) { scrollStatus = '滚动底部' }else { scrollStatus = '滚动中' }*/ // // 判断滚动状态(办法2) if(status == 'top') { scrollStatus = '滚动至顶部' }else if(status == 'bottom') { scrollStatus = '滚动底部' }else { scrollStatus = '滚动中' } }</script>
OK,以上就是svelte.js自定义零碎丑化滚动条组件的分享。后续还会分享一个svelte桌面端实例我的项目。
最初附上一个svelte3聊天实战我的项目
svelte-chat基于svelte3.x仿微信APP聊天我的项目
目前svelte.js稳定性还能够,生态也逐步完善,期待更多的开发小伙伴一起参加进来。