-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
实现一个自定义滚动条 #11
Comments
@cobish 呀,sorry,改正了 |
最后 查看scrollbar组件的链接失效了~ |
你好, |
https://github.com/linzx1993/aps-ui/tree/master/src/components/scrollbar |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
首先,我们先把需要实现的功能先确定下来。
前面两点依靠原生滚动条其实比较简单,但是在第三点上实在是卡了我好久,想了好久都没有想出来。最后还是看了element源码才实现成功。
接下去我会以垂直滚动条为例(水平滚动条基本同理),实现一个自定义的滚动条出来。我争取把其中原理细节讲清楚。
1、搭建好基本的样式框架
开始我们先把HTML和样式写好
第一步的HTML和CSS
滚动条的框架如上面所示,接下午我会以简称
wrap
,bar
,thumb
进行简称wrap
:内容区域包裹框bar
: 包裹区域中自定义滚动条的滚动框thumb
:自定义滚动条1.1计算出滚动条的宽度。
第一步我们先将原生的滚动条隐藏掉。但是这里涉及到第一个问题,那就是不同浏览器的下滚动条宽度是不一样的。我们需要准确的知道,如果
wrap
产生了滚动条,那它的宽度是多少。先写一个获取到区域内滚动条的宽度(scrollWidth)的回调函数
getScrollWidth
,获取到滚动条高度之后,获取到滚动条的宽度
scrollBarWidth
之后,通过再来设置wrap
的css样式,通过marginRight
将滚动条移动到视线之外1.2计算出滚动条的高度。
第二步我们需要计算出滚动条的高度。计算方法也很简单,元素高度
scrollHieght
/内容高度clientHeight
,得出来的就是滚动条所占的百分比。因为内容高度经常变更,我们可以写一个更新滚动条高度的回调函数
updateThumb
,方便后期s随时调用。到了这一步,基本上一个滚动条的基本样式已经出来了。接下去我们要实现它的使用功能。
查看第一步的成果
2、添加滚动条滑动功能
到这里我们已经可以看到成型的滚动条的UI界面了,但是仍然缺少滚动和拖动的功能。关键点是在于如何去监听滚动条的变化。
2.1滚轮滑动
还记得文章开头说过,我们所有功能的实现都依赖隐藏起来的原生滚动条。如果大家理解了我上面说的话,那么问题就简单了。当我们开始滑动滚轮的时候,隐藏在暗处的原生滚动条也会同时滚动,此时便会触发原生滚动条的scroll事件。
所以我们只需要写一个相应的回调函数
handleScroll
,在每次触发回调的时候,实时修改我们自定义滚动条的样式就行了。查看滚轮滑动效果
2.2点击滚动框,滚动条及内容移动到相应位置
接下去我们实现第二个功能。当我们点击滚动框的一个位置时,滚动条也会跳到这个位置,同时内容位置也会发生改变。
第一步先获得点击的y坐标,然后计算出和
滚动框bar
顶部的距离,再算出占滚动框的百分比,这个百分比就是滚动条的高度查看点击滚动框的效果
2.3拖动滚动条,移动内容
接下来我们再去实现手动拖拽滚动条去实现移动内容,这个知识点就是拖拽的知识点,不过在看源码的时候发现
element
的习惯很好,他是在当你点击滚动条的时候绑定拖拽,然后松开的时候取消绑定。因为这一块代码比较多,就不贴文章里,大家可以直接链接里看就是了。
查看拖动滚动条的效果
3、实现滚动条随内容实时更新
第二章讲的主要都是实现滚动条功能,这一章讲的是纠结😖我很久的功能。
因为滚动条的高度并不是我们一开始能够确定的,它需要在dom内容渲染出来之后才能确定。而且有时候随着内容的变化,还需要实时改变滚动条的高度。再看了市面上的滚动条之后,发现基本都没有满足这一功能。
事实上缺少了这一点,使用起来是缺少视觉交互的。举个例子,加入一个原来有滚动条的元素因为内容减少导致了滚动条小时,但是自定义滚动条因为没有检测到变化仍然存在,那就会给用户造成困扰。
我不希望每次更新内容都要通过加一步回调函数来更新一下滚动条,而是希望它自己实时更新。在网上没有找到答案之后,最终去翻了element源码,研究了好久,总算找到了想要的答案。
关键点就在于我能前面之前说的那一句话——如果我们改变元素的scrollTop,是会触发scroll事件。
大家想象一个情景,如果滚动条永远出现在最底部,比如下图

那么只要我内容发生了一点变化,滚动条必然会变长或者变短。那么在滚动条长度变化时,scrollTop自然发生了改变(滚动条消失则scrollTop变为0),那么就会触发scroll的回调函数,那么我们就自动监测到了啊😊。
在明白了这一点后,却又冒出来一个问题。正常情况下,滚动条不可能出现在最底部啊,那怎么办呢?
element
选择了自己造一个置于底部的滚动条来满足自己需求。做了个demo,查看效果点这里
ul
是我们包裹内容的DOM元素。配合着css来看,第一段JS我们创建出了
resizeTrigger
这个div,并且我们将他的height:100%
。这样子如果内容发生变化,resizeTrigger
永远和父元素ul
同时改变高度。这里设置成高度100%非常重要,这样子才能主动同步到内容的变化。注意到
resizeTrigger
里面还有有一个父子元素expand
和expandChild
。在第二段JS的resetTrigger
函数中。然后设置expandChild
的高度超过父元素expand
的高度,促使expand
产生滚动条。然后我们再将滚动条的scrollTop
设置为最大,这样子滚动条就会出现在滚动区域resizeTrigger
的最底部了。现在我们做到了将滚动条设置在了最底部,所以只要内容发生了变化,那么滚动条的scrollTop必然也会发生变化。
最后一段代码就是scroll的监听。当监听到
scrollTop
值发生变化时,触发相应的回调函数。所以这块代码最后的逻辑其实是这样的。内容改变 -->
ul
高度改变-->resizeTrigger
高度改变 -->expand
滚动条的scrollTop
发生变化 --> 触发scroll的回调函数,在函数里面调整再次调整滚动条的高度,保证滚动条高度正确。通过这三段代码,我们也基本实现了自动监听内容变化来更新滚动条。
简单画了个配图来帮助理解逻辑

通过两个小蓝框产生的滚动条来帮助监听内容变化
4、实现组件化,方便开发者使用
经过以上3大步基本上是可以实现一个自定义的滚动条的。上面的代码是面向原生js的。在我们的项目里面,实现第4点是通过封装成一个scrollbar的的组件,在项目里面进行使用。
这一条要求因为不同框架实现方式都不一样,所以就不详细贴代码了,不过最终原理肯定还是一致的。因为自己项目用的是一个Vue框架,所以是个Vue组件,有需求可以自己去看。
没有写过写Vue组件的可以看看这一篇,少踩些坑
查看scrollbar组件
好了文章就到此结束了,在看人家源码的过程中也学到了许多。比如使用JSX来编写组件;scroll监听其实就是判断scrollTop;比如通过自己造滚动条的方法监听scrollTop来实现自动更新。最后通过写文章,对一些新的知识点理解还是加深了许多。
The text was updated successfully, but these errors were encountered: