深入分析element ScrollBar滚动组件源码(3)

render(h) { const { size, move, bar } = this; return ( <div class={ ['el-scrollbar__bar', 'is-' + bar.key] } onMousedown={ this.clickTrackHandler } > <div ref="thumb" onMousedown={ this.clickThumbHandler } style={ renderThumbStyle({ size, move, bar }) }> </div> </div> ); }

render函数获取父组件传递的size,move之后,通过 renderThumbStyle 来生成thumb,并且给track和thumb分别绑定了onMousedown事件。

clickThumbHandler(e) { this.startDrag(e); // 记录this.y , this.y = 鼠标按下点到thumb底部的距离 // 记录this.x , this.x = 鼠标按下点到thumb左侧的距离 this[this.bar.axis] = (e.currentTarget[this.bar.offset] - (e[this.bar.client] - e.currentTarget.getBoundingClientRect()[this.bar.direction])); }, // 开始拖拽函数 startDrag(e) { e.stopImmediatePropagation(); // 标识位, 标识当前开始拖拽 this.cursorDown = true; // 绑定mousemove和mouseup事件 on(document, 'mousemove', this.mouseMoveDocumentHandler); on(document, 'mouseup', this.mouseUpDocumentHandler); // 解决拖动过程中页面内容选中的bug document.onselectstart = () => false; }, mouseMoveDocumentHandler(e) { // 判断是否在拖拽过程中, if (this.cursorDown === false) return; // 刚刚记录的this.y(this.x) 的值 const prevPage = this[this.bar.axis]; if (!prevPage) return; // 鼠标按下的位置在track中的偏移量,即鼠标按下点到track顶部(左侧)的距离 const offset = ((this.$el.getBoundingClientRect()[this.bar.direction] - e[this.bar.client]) * -1); // 鼠标按下点到thumb顶部(左侧)的距离 const thumbClickPosition = (this.$refs.thumb[this.bar.offset] - prevPage); // 当前thumb顶部(左侧)到track顶部(左侧)的距离,即thumb向下(向右)偏移的距离 占track高度(宽度)的百分比 const thumbPositionPercentage = ((offset - thumbClickPosition) * 100 / this.$el[this.bar.offset]); // wrap.scrollHeight / wrap.scrollLeft * thumbPositionPercentage得到wrap.scrollTop / wrap.scrollLeft // 当wrap.scrollTop(wrap.scrollLeft)发生变化的时候,会触发父组件wrap上绑定的onScroll事件, // 从而重新计算moveX/moveY的值,这样thumb的滚动位置就会重新渲染 this.wrap[this.bar.scroll] = (thumbPositionPercentage * this.wrap[this.bar.scrollSize] / 100); }, mouseUpDocumentHandler(e) { // 当拖动结束,将标识位设为false this.cursorDown = false; // 将上一次拖动记录的this.y(this.x)的值清空 this[this.bar.axis] = 0; // 取消页面绑定的mousemove事件 off(document, 'mousemove', this.mouseMoveDocumentHandler); // 清空onselectstart事件绑定的函数 document.onselectstart = null; }

上面的代码就是thumb滚动条拖拽的所有处理逻辑,整体思路就是在拖拽thumb的过程中,动态的计算thumb顶部(左侧)到track顶部(左侧)的距离占track本身高度(宽度)的百分比,然后利用这个百分比动态改变wrap.scrollTop的值,从而触发页面滚动以及滚动条位置的重新计算,实现滚动效果。

深入分析element ScrollBar滚动组件源码

上一个图方便大家理解吧( ̄▽ ̄)"

track的onMousedown和trumb的逻辑也差不多,有两点需要注意:

track的onMousedown事件回调中不会给页面绑定mousemove和mouseup事件,因为track相当于click事件 在track的onmousedown事件中,我们计算thumb顶部到track顶部的方法是,用鼠标点击点到track顶部的距离减去thumb的二分之一高度,这是因为点击track之后,thumb的中点刚好要在鼠标点击点的位置。

至此,整个scrollbar源码就分析结束了,回过头来看看,其实scrollbar的实现并不难,主要还是要理清各种滚动关系、thumb的长度以及滚动位置怎么通过wrap,view之间的关系来确定。这一部分可能比较绕,没搞懂的同学建议自己手动画画图研究一下,只要搞懂这个滚动原理,实现起来就很简单了。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/37300c9850317cc6c797156f29ca1083.html