Open linzx1993 opened 6 years ago
“查看拖动滚动条的效果”,该链接跳错了~
@cobish 呀,sorry,改正了
最后 查看scrollbar组件的链接失效了~
你好, 查看scrollbar组件的链接失效了~ 有完整版的vue组件源码吗
你好, 查看scrollbar组件的链接失效了~ 有完整版的vue组件源码吗
https://github.com/linzx1993/aps-ui/tree/master/src/components/scrollbar
首先,我们先把需要实现的功能先确定下来。
前面两点依靠原生滚动条其实比较简单,但是在第三点上实在是卡了我好久,想了好久都没有想出来。最后还是看了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来实现自动更新。最后通过写文章,对一些新的知识点理解还是加深了许多。