scrollBar.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. 用途项目:自定义滚动条实现
  3. */
  4. (function(win, doc, $){
  5. // 定义的滚动条的构造函数
  6. function CusScrollBar(options) {
  7. // 函数的调用
  8. this._init(options);
  9. }
  10. // 对象的合并
  11. $.extend(CusScrollBar.prototype, {
  12. _init: function(options){
  13. // 闭包
  14. var self = this;
  15. // 初始化参数
  16. self.options = {
  17. scrollDir: 'Y', //滚动的方向
  18. contentSelector: '', //滚动内容区选择器
  19. barSelector: '', //滚动条选择器
  20. sliderSelector: '', //滚动滑块选择器
  21. wheelStep: 10, //滚动步长(鼠标移动一下,内容滚动的幅度)
  22. }
  23. // 覆盖参数
  24. $.extend(true, self.options, options||{});
  25. self._initDomEvent();
  26. $(window).on("resize",function(){
  27. self._initDomEvent();
  28. })
  29. return self;
  30. },
  31. /**
  32. * 初始化DOM引用
  33. * @method _initDomEvent
  34. * @return {CusScrollBar}
  35. */
  36. _initDomEvent: function() {
  37. var opts = this.options;
  38. // 滚动内容区对象,必填项
  39. this.$cont = $(opts.contentSelector);
  40. // 滚动条滑块对象,必须项
  41. this.$slider = $(opts.sliderSelector);
  42. // 滚动条对象
  43. this.$bar = opts.barSelector ? $(opts.barSelector) : self.$slider.parent();
  44. //滚动方向
  45. this.$scrollDir = opts.scrollDir || "Y"
  46. // 获取文档对象
  47. this.$doc = $(doc);
  48. // 获取初始化滑块拖动功能
  49. this._initSliderDragEvent();
  50. // 获取同步滑块的位置
  51. this._bindContentScroll();
  52. // 获取鼠标滚轮事件
  53. this._bindMousewheel();
  54. // 获取内容来定义滑块的高度
  55. this._initSliderHeight();
  56. },
  57. // 根据内容来定义滑块的高度
  58. _initSliderHeight: function() {
  59. var rate;
  60. var sliderHeight;
  61. if(this.$scrollDir == "Y"){
  62. rate = this.$cont.height() /this.$cont[0].scrollHeight;
  63. this.$bar.css({
  64. "top": "0px"
  65. })
  66. sliderHeight = rate*this.$bar.height();
  67. this.$slider.css('height',sliderHeight);
  68. }else{
  69. rate = this.$cont.width() /this.$cont[0].scrollWidth;
  70. this.$bar.css({
  71. "width": "100%",
  72. "height": "5px",
  73. "bottom": "0px",
  74. "zIndex": "100"
  75. })
  76. this.$slider.css({
  77. "height":"5px"
  78. })
  79. sliderHeight = rate*this.$bar.width();
  80. this.$slider.css('width',sliderHeight);
  81. }
  82. if(rate === 1){
  83. this.$bar.css('display','none');
  84. }
  85. // this.$slider.css('height',sliderHeight);
  86. },
  87. /**
  88. * 初始化滑块拖动功能
  89. * @return {[Object]} [this]
  90. */
  91. _initSliderDragEvent: function() {
  92. var self = this;
  93. // 滑块元素
  94. var slider = this.$slider,
  95. sliderEl = slider[0];
  96. // 如果元素存在
  97. if (sliderEl) {
  98. var doc = this.$doc,
  99. dragStartPagePostion,
  100. dragStartScrollPostion,
  101. dragContBarRate;
  102. function mousemoveHandler(e) {
  103. e.preventDefault();
  104. if (dragStartPagePostion == null) {
  105. return;
  106. }
  107. //内容开始卷曲的高度+rate*(鼠标释放的位置-开始的位置) == 就是内容滑动的位置
  108. if(self.$scrollDir == "Y"){
  109. self.scrollTo(dragStartScrollPostion + (e.pageY - dragStartPagePostion)*dragContBarRate);
  110. }else{
  111. self.scrollTo(dragStartScrollPostion + (e.pageX - dragStartPagePostion)*dragContBarRate);
  112. }
  113. }
  114. slider.on('mousedown', function(e){
  115. e.preventDefault();
  116. e.stopPropagation()
  117. if(self.$scrollDir == "Y"){
  118. // 获取鼠标的点击的开始位置
  119. dragStartPagePostion = e.pageY;
  120. // 获取内容区域的向上卷区的高度
  121. dragStartScrollPostion = self.$cont[0].scrollTop;
  122. dragContBarRate = self.getMaxScrollPosition()/self.getMaxSliderPosition();
  123. }else{
  124. // 获取鼠标的点击的开始位置
  125. dragStartPagePostion = e.pageX;
  126. // 获取内容区域的向上卷区的高度
  127. dragStartScrollPostion = self.$cont[0].scrollLeft;
  128. dragContBarRate = self.getMaxScrollPosition()/self.getMaxSliderPosition();
  129. }
  130. // 监听的document对象
  131. doc.on('mousemove.scroll', mousemoveHandler).on('mouseup.scroll',function(){
  132. doc.off('.scroll');
  133. });
  134. });
  135. this.$bar.on("click",function(e){
  136. var scrollHei
  137. dragContBarRate = self.getMaxScrollPosition()/self.getMaxSliderPosition();
  138. if(self.$scrollDir == "Y"){
  139. if(e.offsetY > slider.height()){
  140. self.scrollTo((e.offsetY - slider.height())*dragContBarRate);
  141. }else{
  142. self.scrollTo(e.offsetY*dragContBarRate);
  143. }
  144. }else{
  145. if(e.offsetX > slider.width()){
  146. self.scrollTo((e.offsetX - slider.width())*dragContBarRate);
  147. }else{
  148. self.scrollTo(e.offsetX*dragContBarRate);
  149. }
  150. }
  151. // dragStartScrollPostion = self.$cont[0].scrollTop;
  152. })
  153. return self;
  154. }
  155. },
  156. // 计算滑块的当前位置
  157. getSliderPosition: function() {
  158. var self = this,
  159. // 滑块可以移动的距离
  160. maxSliderPosition = self.getMaxSliderPosition();
  161. // 滑块移动的距离
  162. var sliderPosition;
  163. if(self.$scrollDir == "Y"){
  164. sliderPosition = Math.min(maxSliderPosition, maxSliderPosition*self.$cont[0].scrollTop/self.getMaxScrollPosition());
  165. }else{
  166. sliderPosition = Math.min(maxSliderPosition, maxSliderPosition*self.$cont[0].scrollLeft/self.getMaxScrollPosition());
  167. }
  168. return sliderPosition;
  169. },
  170. // 内容可滚动的高度
  171. getMaxScrollPosition: function() {
  172. var self = this;
  173. var maxScrollPosition;
  174. if(self.$scrollDir == "Y"){
  175. maxScrollPosition = Math.max(self.$cont.height(), self.$cont[0].scrollHeight) - self.$cont.height();
  176. }else{
  177. maxScrollPosition = Math.max(self.$cont.width(), self.$cont[0].scrollWidth) - self.$cont.width();
  178. }
  179. return maxScrollPosition
  180. },
  181. //滑块可移动的距离
  182. getMaxSliderPosition: function(){
  183. var self = this;
  184. const paddingTop = parseInt(self.$cont.css("paddingTop"))
  185. const paddingBottom = parseInt(self.$cont.css("paddingBottom"))
  186. const paddingLeft = parseInt(self.$cont.css("paddingLeft"))
  187. const paddingRight = parseInt(self.$cont.css("paddingRight"))
  188. if(self.$scrollDir == "Y"){
  189. return self.$bar.height()+paddingTop*3+paddingBottom*3 + - self.$slider.height();
  190. }else{
  191. return self.$bar.width()+paddingLeft*3+paddingRight*3 + - self.$slider.width();
  192. }
  193. },
  194. // 监听内容的滚动,同步滑块的位置
  195. _bindContentScroll: function() {
  196. var self = this;
  197. self.$cont.on('scroll', function(){
  198. var sliderEl = self.$slider && self.$slider[0];
  199. if (sliderEl) {
  200. // 设置滑块的位置
  201. if(self.$scrollDir == "Y"){
  202. sliderEl.style.top = self.getSliderPosition() + 'px';
  203. }else{
  204. sliderEl.style.left = self.getSliderPosition() + 'px';
  205. }
  206. }
  207. });
  208. return self;
  209. },
  210. // 鼠标滚轮事件
  211. _bindMousewheel: function() {
  212. var self = this;
  213. // on监听事件,多个事件利用空格分开
  214. self.$cont.on('mousewheel DOMMouseScroll',function(e){
  215. e.preventDefault();
  216. // 判断原生事件对象的属性
  217. var oEv = e.originalEvent,
  218. //原生事件对象,(其他浏览器负数向下,firefox正数向下,所以在wheelDelta前面有负数)
  219. // 想要达到的效果,鼠标向下滚动,内容向下走
  220. wheelRange = oEv.wheelDelta ? -oEv.wheelDelta/120 : (oEv.detail || 0)/3;
  221. // 调用scrollTo方法。
  222. self.scrollTo(self.$cont[0].scrollTop + wheelRange*self.options.wheelStep)
  223. if(self.$cont[0].scrollTop !==0 ){
  224. e.stopPropagation()
  225. }
  226. });
  227. },
  228. // 内容的滑动
  229. scrollTo: function(positonVal) {
  230. var self = this;
  231. if(self.$scrollDir =="Y"){
  232. self.$cont.scrollTop(positonVal);
  233. }else{
  234. self.$cont.scrollLeft(positonVal);
  235. }
  236. }
  237. });
  238. win.CusScrollBar = CusScrollBar;
  239. })(window,document,jQuery)