13693261870
2024-04-02 2a1b873b4b78b508d5d53c57992e734c56619df8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
用途项目:自定义滚动条实现
*/
(function(win, doc, $){
  // 定义的滚动条的构造函数
  function CusScrollBar(options) {
    // 函数的调用
    this._init(options);
  }
  // 对象的合并
  $.extend(CusScrollBar.prototype, {
    _init: function(options){
      // 闭包
      var self = this;
      // 初始化参数
      self.options = {
        scrollDir: 'Y',       //滚动的方向
        contentSelector: '',  //滚动内容区选择器
        barSelector: '',      //滚动条选择器
        sliderSelector: '',   //滚动滑块选择器
        wheelStep: 100,        //滚动步长(鼠标移动一下,内容滚动的幅度)
      }
      // 覆盖参数
      $.extend(true, self.options, options||{});
      self._initDomEvent();
      return self;
    },
 
    /**
     * 初始化DOM引用
     * @method _initDomEvent
     * @return {CusScrollBar}
     */
     _initDomEvent: function() {
      var opts = this.options;
      // 滚动内容区对象,必填项
      this.$cont = $(opts.contentSelector);
      // 滚动条滑块对象,必须项
      this.$slider = $(opts.sliderSelector);
      // 滚动条对象
      this.$bar = opts.barSelector ? $(opts.barSelector) : self.$slider.parent();
      // 获取文档对象
      this.$doc = $(doc);
      // 获取初始化滑块拖动功能
      this._initSliderDragEvent();
      // 获取同步滑块的位置
      this._bindContentScroll();
      // 获取鼠标滚轮事件
      this._bindMousewheel();
      // 获取内容来定义滑块的高度
      this._initSliderHeight();
 
     },
     // 根据内容来定义滑块的高度
     _initSliderHeight: function() {
      var rate = this.$cont.height()/this.$cont[0].scrollHeight;
      var sliderHeight = rate*this.$bar.height();
      this.$slider.css('height',sliderHeight);
     },
     
 
     /**
      * 初始化滑块拖动功能
      * @return {[Object]} [this]
      */
    _initSliderDragEvent: function() {
      var self = this;
      // 滑块元素
      var slider = this.$slider,
          sliderEl = slider[0];
      // 如果元素存在
      if (sliderEl) {
        var doc = this.$doc,
            dragStartPagePostion,
            dragStartScrollPostion,
            dragContBarRate;
        function mousemoveHandler(e) {
          e.preventDefault();
          if (dragStartPagePostion == null) {
            return;
          }
          //内容开始卷曲的高度+rate*(鼠标释放的位置-开始的位置) == 就是内容滑动的位置
          self.scrollTo(dragStartScrollPostion + (e.pageY - dragStartPagePostion)*dragContBarRate);
        }
        slider.on('mousedown', function(e){
          e.preventDefault();
          // 获取鼠标的点击的开始位置
          dragStartPagePostion = e.pageY;
          // 获取内容区域的向上卷区的高度
          dragStartScrollPostion = self.$cont[0].scrollTop;
          dragContBarRate = self.getMaxScrollPosition()/self.getMaxSliderPosition();
          // 监听的document对象
          doc.on('mousemove.scroll', mousemoveHandler).on('mouseup.scroll',function(){
            doc.off('.scroll');
          });
        });
        return self;
      }
    },
    
    // 计算滑块的当前位置
    getSliderPosition: function() {
      var self = this,
      // 滑块可以移动的距离
          maxSliderPosition = self.getMaxSliderPosition();
          // 滑块移动的距离
      return Math.min(maxSliderPosition, maxSliderPosition*self.$cont[0].scrollTop/self.getMaxScrollPosition());
    },
 
    // 内容可滚动的高度
    getMaxScrollPosition: function() {
      var self = this;
      return Math.max(self.$cont.height(), self.$cont[0].scrollHeight) - self.$cont.height();
    
    },
 
    //滑块可移动的距离
    getMaxSliderPosition: function(){
      var self = this;
      return self.$bar.height() - self.$slider.height();
    },
 
    // 监听内容的滚动,同步滑块的位置
    _bindContentScroll: function() {
      var self = this;
      self.$cont.on('scroll', function(){
        var sliderEl = self.$slider && self.$slider[0];
        if (sliderEl) {
          // 设置滑块的位置
          sliderEl.style.top = self.getSliderPosition() + 'px';
        }
      });
      return self;
    },
 
    // 鼠标滚轮事件
    _bindMousewheel: function() {
      var self = this;
      // on监听事件,多个事件利用空格分开
      self.$cont.on('mousewheel DOMMouseScroll',function(e){
        e.preventDefault();
        // 判断原生事件对象的属性
        var oEv = e.originalEvent,
        //原生事件对象,(其他浏览器负数向下,firefox正数向下,所以在wheelDelta前面有负数)
        // 想要达到的效果,鼠标向下滚动,内容向下走
            wheelRange = oEv.wheelDelta ? -oEv.wheelDelta/120 : (oEv.detail || 0)/3;
            // 调用scrollTo方法。
            self.scrollTo(self.$cont[0].scrollTop + wheelRange*self.options.wheelStep)
      });
    },
 
    // 内容的滑动
    scrollTo: function(positonVal) {
      var self = this;
      self.$cont.scrollTop(positonVal);
    }
  });
 
  win.CusScrollBar = CusScrollBar;
})(window,document,jQuery)