效果图:
这篇文章主要讲解js交互,就不用篇幅去告诉大家怎么写html css了,让文章言简意赅。
大体思路:
如何实现滚动滑块,让滑块与内容一起联动呢?请看下图:
首先来看,
空心鼠标位置与实心鼠标位置的距离 是不是等于滑块移动的距离X0 呢?
答:等于
滑块移动的最大距离X0是多少呢?
答:滚动条的高度X - 滑块的高度
内容能滚动最大高度Y0是多少呢?
答:内容总高度Y - 内容可视区的高度
通过比较:可以得出滚动比率:
那么代码应该怎么写呢:
第一步: 获取鼠标移动距离 = 滑块移动距离
第二步: 获取滑块可移动的距离
第三步: 内容可滚动的高度
第四步: 通过上面的滚动比例关系可以获取内容滚动高度
最五步:设置滑块的位置
插件封装大框:
- 首先创建一个构造函数CusScrollBar
- 然后通过new操作符实例化这个构造函数,并调用初始化函数_init,_init是这个实例初始化的入口。
补充:(自调用匿名函数:通过创建一个自调用匿名函数,创建一个特殊的函数作用域,该作用域中的代码不会和已有的同名函数、方法和变量以及第三方库发生冲突。)
- win,doc,$: 对应外部传过来的window对象,document对象,jQuery对象。
- CusScrollBar: 创建一个构造函数,并调用初始化函数_init()。
- [options]: 实例化参数传入到_init函数中
- this: 代表实例
原型上添加方法:
方案1:
CusScrollBar.prototype._init = function () {
console.log("test");
}
方案2: (基于jquery的extend方法)
$.extend(CusScrollBar.prototype, {
A: function () {},
B: function () {}
})
补充:$.extend方法 :
暴露构造函数,使外部可调用:
win.CusScrollBar = CusScrollBar;
上面的大框讲解完成了,下面开始讲解原型上定义的方法:
_init()函数:
1 _init: function (options) {
2 // 保存外部的this 这里的this =》 CusScrollBar
3 var self = this;
4 // 配置默认参数
5 self.options = {
6 scrollDir: 'y', // 滚动的方向
7 contSelector: '', // 滚动内容区选择器
8 barSelector: '', // 滚动条选择器
9 sliderSelector: '', // 滚动滑块儿选择器
10 correctSelector: '.correct-bot', // 矫正元素
11 };
12 // 通过深拷贝将外部参数与默认参数合并
13 $.extend(true, self.options, options || {});
14 // 调用_initDomEvent方法
15 self._initDomEvent();
16 // 返回self,实现链式调用
17 return self;
18 },
_initDomEvent()函数:
1 _initDomEvent: function () {
2 var opts = this.options;
3 // 滚动内容区对象,必须填
4 this.$cont = $(opts.contSelector);
5 // 滚动条滑块对象,必须填
6 this.$slider = $(opts.sliderSelector);
7 // 滚动条对象
8 this.$bar = opts.barSelector ?
9 $(opts.barSelector) :
10 self.$slider.parent();
11 // 获取文档对象
12 this.$doc = $(doc);
13 // 矫正元素对象
14 this.$correct = $(opts.correctSelector);
15 this._initSliderDragEvent()
16 ._bindContScroll();
17 },
_initSliderDragEvent()函数
1 _initSliderDragEvent: function () {
2 var slider = this.$slider,
3 sliderEl = slider[0],
4 self = this;
5 if (sliderEl) {
6 var doc = this.$doc,
7 // 拖动起始位置
8 dragStartPagePosition,
9 //
10 dragStartScrollPosition,
11 // 拖动比例
12 dragContBarRate;
13
14 function mousemoveHandler(e) {
15 e.preventDefault();
16 console.log('mousemove');
17 if (dragStartPagePosition == null) return;
18 self.scrollTo(
19 dragStartScrollPosition +
20 (e.pageY - dragStartPagePosition) * dragContBarRate
21 );
22 }
23
24 // 绑定事件
25 slider.on('mousedown', function (e) {
26 // 阻止浏览器默认行为
27 e.preventDefault();
28 console.log('mousedown');
29 dragStartPagePosition = e.pageY;
30 dragStartScrollPosition = self.$cont[0].scrollTop;
31 dragContBarRate =
32 self.getMaxScrollPosition() / self.getMaxSliderPosition();
33
34 // 在document上绑定mousemove事件,是为了当没有松开鼠标,但是鼠标移出滚轮时依然能够触发mousemove事件,提升用户体验。
35 doc
36 .on('mousemove.scroll', mousemoveHandler)
37 .on('mouseup.scroll', function (e) {
38 console.log('mouseup');
39 doc.off('.scroll');
40 });
41 });
42 }
43 return self;
44 },
getMaxSliderPosition()
1 // 滑动可移动的距离
2 getMaxSliderPosition: function () {
3 var self = this;
4 return self.$bar.height() - self.$slider.height();
5 },
mousemoveHandler()
1 function mousemoveHandler(e) {
2 e.preventDefault();
3 console.log('mousemove');
4 if (dragStartPagePosition == null) return;
5 self.scrollTo(
6 dragStartScrollPosition +
7 (e.pageY - dragStartPagePosition) * dragContBarRate
8 );
9 }
scrollTo()
1 // 移动到具体位置
2 scrollTo: function (positionVal) {
3 var self = this;
4 self.$cont.scrollTop(positionVal);
5 },
_bindContScroll()
1 // 监听内容的滚动,同步滑块的位置
2 _bindContScroll: function () {
3 var self = this;
4 self.$cont.on('scroll', function () {
5 var sliderEl = self.$slider && self.$slider[0];
6 if (sliderEl) {
7 sliderEl.style.top = self.getSliderPosition() + 'px';
8 }
9 });
10 return self;
11 },
getSliderPosition()
// 计算滑块儿的当前位置
getSliderPosition: function () {
var self = this,
maxSliderPosition = self.getMaxSliderPosition();
return Math.min(
maxSliderPosition,
maxSliderPosition *
self.$cont[0].scrollTop /
self.getMaxScrollPosition()
);
},