自定义滚动条的实现思路与关键算法

本文介绍了自定义滚动条的三种实现思路,重点讲解了使用JavaScript实现自定义滚动条的详细步骤,包括监听滚动事件、计算滑块大小与位置、滑块拖拽、点击滚动轨道滚动、平滑滚动、键盘导航、内容选中滚动等,旨在帮助开发者理解自定义滚动条的实现逻辑和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在web开发中,自定义滚动条是个常见的需求,虽然浏览器原生的滚动条很强大并且在大多数场景下表现的很好,但某些时候我们仍然希望修改他的样式,比如变细一点,或者去掉圆角和轨道,又或者隐藏他们。这些都属于自定义行为,本篇文章将介绍自定义滚动条的几种实现思路,并着重讲解最流行的js方案。


上图是自定义的效果(视频在转换时降速了,其实非常快)

在正文开始前,我们先统一滚动条各个部分的名称。


一、实现思路

实现自定义滚动条的方式不止一种,这里列出三种方式。

1、css修改。

这是最简单的方式,你可以通过::-webkit-scrollbar这个css伪类选择器去修改滚动条样式,包括滚动条轨道、滑块以及上下箭头等,但它只支持webkit内核的浏览器,并且它不是css标准的一部分,这意味着除了浏览器兼容性问题外,将来还可能被浏览器厂商删掉并转而采用新标准。

2、自行实现滚动条部分,但scroll行为交给浏览器原生实现。

这种思路的关键是不能将容器的overflow设为hidden,这样虽然隐藏了滚动条,但也禁止了滚动行为。所以开发者尝试将滚动条遮盖起来,一般通过多个div的嵌套和偏移(偏移量恰好是滚动条的宽度)来实现。遮盖后再将模拟的滚动条固定在容器右侧和底部。之后的关键点就是计算模拟滚动条的宽高与位置,并且监听容器的scroll事件,及时更新滚动条的状态,如果用户拖动滚动条,则此时不能依靠原生滚动行为,需要自己计算实际滚动距离去更新容器的scrollLeft及scrollTop。参考simplebarreact-custom-scrollbars

该方案有很多优点,首先你可以完全自定义滚动条的样式而不用考虑兼容性问题,其次它的性价比非常高,绝大多数时间,你使用的是浏览器默认的行为(他们性能优秀而且覆盖了边际情况),只有在用户拖动滚动条时,才需要手动计算并更新容器的滚动距离。不过该方案也并非完美无缺,最大的问题是你需要添加多层div才能覆遮盖住原生滚动条,这在一定程度上破坏了开发者预先设想的文档结构。

3、自行实现滚动行为与滚动条样式。

该方案比较复杂,因为滚动行为通常由三个条件触发,分别是鼠标滚轮(或触控板)滑动、键盘导航、鼠标拖动(选择文字时),你得同时监听这三种事件,同时要考虑兼容问题,因为这三种事件在各个浏览器不统一。滚动条部分与方案2相同,这里不再赘述。 虽然这个方案不好搞,但正因为完全自定义,你得以写出更丰富的滚动逻辑,比如整屏滚动或者增加颜色特效。该方案在社区最为流行。

二、js实现思路(pc端)

这里会详细阐述方案3的实现思路。让我们从零开始,现在有一个容器,他的子元素高度超过了容器的高度,需要给他添加一个纵向的滚动条,从交互角度出发,可以分解成以下步骤。

1、监听容器的mousewheel事件。

通过鼠标滚轮或者触控板的滑动,浏览器会生成mousewheel事件,事件中带有滚动偏移量,我们要利用该数值来修改容器的scrollTop以达到滚动效果。这里的问题是mousewheel不是一个标准事件,各个浏览器携带不一样的事件信息,滚动偏移量也不同,所以我们需要抹平他们的差异。一个好的办法是将滚动偏移量统一设为1。

const userAgent = window.navigator.userAgent; 
let isSafari = (userAgent.indexOf('Chrome') === -1) && (userAgent.indexOf('Safari') >= 0);
function standardizedWheel(e) {  
  let wheelEvent = Object.assign({}, e);  
  // vertical    
  if (typeof e.wheelDeltaY !== 'undefined') {    
    // webkit        
    wheelEvent.deltaY = e.whee
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值