scrollBar.js 9.3 KB

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