Some time ago, I shared with you two svelte3.x series components. Today, I will continue to share a newly written svelte3-scrollbar
virtual beautification system scroll bar component.
svelte-layer: a svelte3.x lightweight PC-side pop-up window component
svelte-popup: a svelte3.x mobile terminal popup component
svelte-scrollbar is a lightweight web page custom beautification system scroll bar component. Support 原生滚动条、自动隐藏、垂直+水平滚动、自定义滚动条大小/颜色/间隙
and other functions.
Create a new Scrollbar component in the lib directory.
import components
Introduce plugins to pages that require scroll bar functionality.
import Scrollbar from '$lib/Scrollbar'
quick call
Called in the following way to quickly generate a virtualized scroll bar.
<!-- //原生滚动条 -->
<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>
parameter configuration
svelte-scrollbar supports the following parameter configurations.
<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>
Template and logic section
<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>
Also supports dynamic monitoring of scroll events.
<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, the above is the sharing of the svelte.js custom system beautification scroll bar component. A svelte desktop example project will be shared in the future.
Finally, attach a svelte3 chat actual project
svelte-chat is based on the svelte3.x imitation WeChat APP chat project
At present, the stability of svelte.js is OK, and the ecology is gradually improving. We look forward to more development partners participating together.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。