scrollBar.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. if(!this.$bar.css("top")){
  64. this.$bar.css({
  65. "top": "0px"
  66. })
  67. }
  68. sliderHeight = rate*this.$bar.height();
  69. this.$slider.css('height',sliderHeight);
  70. }else{
  71. rate = this.$cont.width() /this.$cont[0].scrollWidth;
  72. this.$bar.css({
  73. "width": "100%",
  74. "height": "5px",
  75. "bottom": "0px",
  76. "zIndex": "100",
  77. })
  78. this.$slider.css({
  79. "height":"5px"
  80. })
  81. sliderHeight = rate*this.$bar.width();
  82. this.$slider.css('width',sliderHeight);
  83. }
  84. if(rate === 1){
  85. this.$bar.css('display','none');
  86. }
  87. // this.$slider.css('height',sliderHeight);
  88. },
  89. /**
  90. * 初始化滑块拖动功能
  91. * @return {[Object]} [this]
  92. */
  93. _initSliderDragEvent: function() {
  94. var self = this;
  95. // 滑块元素
  96. var slider = this.$slider,
  97. sliderEl = slider[0];
  98. // 如果元素存在
  99. if (sliderEl) {
  100. var doc = this.$doc,
  101. dragStartPagePostion,
  102. dragStartScrollPostion,
  103. dragContBarRate;
  104. function mousemoveHandler(e) {
  105. e.preventDefault();
  106. if (dragStartPagePostion == null) {
  107. return;
  108. }
  109. //内容开始卷曲的高度+rate*(鼠标释放的位置-开始的位置) == 就是内容滑动的位置
  110. if(self.$scrollDir == "Y"){
  111. self.scrollTo(dragStartScrollPostion + (e.pageY - dragStartPagePostion)*dragContBarRate);
  112. }else{
  113. self.scrollTo(dragStartScrollPostion + (e.pageX - dragStartPagePostion)*dragContBarRate);
  114. }
  115. }
  116. slider.on('mousedown', function(e){
  117. e.preventDefault();
  118. e.stopPropagation()
  119. if(self.$scrollDir == "Y"){
  120. // 获取鼠标的点击的开始位置
  121. dragStartPagePostion = e.pageY;
  122. // 获取内容区域的向上卷区的高度
  123. dragStartScrollPostion = self.$cont[0].scrollTop;
  124. dragContBarRate = self.getMaxScrollPosition()/self.getMaxSliderPosition();
  125. }else{
  126. // 获取鼠标的点击的开始位置
  127. dragStartPagePostion = e.pageX;
  128. // 获取内容区域的向上卷区的高度
  129. dragStartScrollPostion = self.$cont[0].scrollLeft;
  130. dragContBarRate = self.getMaxScrollPosition()/self.getMaxSliderPosition();
  131. }
  132. // 监听的document对象
  133. doc.on('mousemove.scroll', mousemoveHandler).on('mouseup.scroll',function(){
  134. doc.off('.scroll');
  135. });
  136. self.$cont.on("mouseleave",function(e){
  137. e.stopPropagation()
  138. doc.off('.scroll');
  139. })
  140. });
  141. slider.on("click",function(e){
  142. e.stopPropagation()
  143. })
  144. this.$bar.on("click",function(e){
  145. var scrollHei
  146. dragContBarRate = self.getMaxScrollPosition()/self.getMaxSliderPosition();
  147. if(self.$scrollDir == "Y"){
  148. if(e.offsetY > slider.height()){
  149. self.scrollTo((e.offsetY - slider.height())*dragContBarRate);
  150. }else{
  151. self.scrollTo(e.offsetY*dragContBarRate);
  152. }
  153. }else{
  154. if(e.offsetX > slider.width()){
  155. self.scrollTo((e.offsetX - slider.width())*dragContBarRate);
  156. }else{
  157. self.scrollTo(e.offsetX*dragContBarRate);
  158. }
  159. }
  160. // dragStartScrollPostion = self.$cont[0].scrollTop;
  161. })
  162. return self;
  163. }
  164. },
  165. // 计算滑块的当前位置
  166. getSliderPosition: function() {
  167. var self = this,
  168. // 滑块可以移动的距离
  169. maxSliderPosition = self.getMaxSliderPosition();
  170. // 滑块移动的距离
  171. var sliderPosition;
  172. if(self.$scrollDir == "Y"){
  173. sliderPosition = Math.min(maxSliderPosition, maxSliderPosition*self.$cont[0].scrollTop/self.getMaxScrollPosition());
  174. }else{
  175. sliderPosition = Math.min(maxSliderPosition, maxSliderPosition*self.$cont[0].scrollLeft/self.getMaxScrollPosition());
  176. }
  177. return sliderPosition;
  178. },
  179. // 内容可滚动的高度
  180. getMaxScrollPosition: function() {
  181. var self = this;
  182. var maxScrollPosition;
  183. if(self.$scrollDir == "Y"){
  184. maxScrollPosition = Math.max(self.$cont.height(), self.$cont[0].scrollHeight) - self.$cont.height();
  185. }else{
  186. maxScrollPosition = Math.max(self.$cont.width(), self.$cont[0].scrollWidth) - self.$cont.width();
  187. }
  188. return maxScrollPosition
  189. },
  190. //滑块可移动的距离
  191. getMaxSliderPosition: function(){
  192. var self = this;
  193. const paddingTop = parseInt(self.$cont.css("paddingTop"))
  194. const paddingBottom = parseInt(self.$cont.css("paddingBottom"))
  195. const paddingLeft = parseInt(self.$cont.css("paddingLeft"))
  196. const paddingRight = parseInt(self.$cont.css("paddingRight"))
  197. if(self.$scrollDir == "Y"){
  198. return self.$bar.height()+paddingTop*3+paddingBottom*3 + - self.$slider.height();
  199. }else{
  200. return self.$bar.width()+paddingLeft*3+paddingRight*3 + - self.$slider.width();
  201. }
  202. },
  203. // 监听内容的滚动,同步滑块的位置
  204. _bindContentScroll: function() {
  205. var self = this;
  206. self.$cont.on('scroll', function(){
  207. var sliderEl = self.$slider && self.$slider[0];
  208. if (sliderEl) {
  209. // 设置滑块的位置
  210. if(self.$scrollDir == "Y"){
  211. sliderEl.style.top = self.getSliderPosition() + 'px';
  212. }else{
  213. sliderEl.style.left = self.getSliderPosition() + 'px';
  214. }
  215. }
  216. });
  217. return self;
  218. },
  219. // 鼠标滚轮事件
  220. _bindMousewheel: function() {
  221. var self = this;
  222. // on监听事件,多个事件利用空格分开
  223. self.$cont.on('mousewheel DOMMouseScroll',function(e){
  224. e.preventDefault();
  225. // 判断原生事件对象的属性
  226. var oEv = e.originalEvent,
  227. //原生事件对象,(其他浏览器负数向下,firefox正数向下,所以在wheelDelta前面有负数)
  228. // 想要达到的效果,鼠标向下滚动,内容向下走
  229. wheelRange = oEv.wheelDelta ? -oEv.wheelDelta/120 : (oEv.detail || 0)/3;
  230. // 调用scrollTo方法。
  231. if(self.$scrollDir =="Y"){
  232. self.scrollTo(self.$cont[0].scrollTop + wheelRange*self.options.wheelStep)
  233. }
  234. if(self.$cont[0].scrollTop !==0 ){
  235. e.stopPropagation()
  236. }
  237. });
  238. },
  239. // 内容的滑动
  240. scrollTo: function(positonVal) {
  241. var self = this;
  242. if(self.$scrollDir =="Y"){
  243. self.$cont.scrollTop(positonVal);
  244. }else{
  245. self.$cont.scrollLeft(positonVal);
  246. }
  247. }
  248. });
  249. win.CusScrollBar = CusScrollBar;
  250. })(window,document,jQuery)