jquery: custom scroll
自定义滚动条实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>自定义滚动条</title> <link rel="stylesheet" href="../css/reset.css"> <style type="text/css"> body { background-color: #ccc; } .scroll-wrap { width: 540px; margin: 30px auto; border: 1px solid #f5f5f5; background-color: #fff; } .scroll-box { position: relative; width: 100%; height: 300px; } .scroll-box .scroll-content { height: 100%; padding: 0 10px; overflow: hidden; } .scroll-box:hover .scroll-bar { display: block; } .scroll-box .scroll-content h3 { font: 16px/3 "Microsoft Yahei"; text-align: center; } .scroll-box .scroll-content p { font-size: 14px; line-height: 20px; text-indent: 2em; margin-bottom: 10px; } .scroll-box .scroll-bar { display: none; position: absolute; top: 0; right: 0; width: 5px; height: 100%; background-color: #fff; } .scroll-box .scroll-bar .scroll-slider { position: absolute; top: 0; left: 1px; width: 3px; border-radius: 25%; background-color: #ddd; } </style> </head> <body> <div class="scroll-wrap"> <!-- 滚动内容区 --> <div class="scroll-box"> <div class="scroll-content"> <h3>title</h3> <p>测试scroll需加长文章长度</p> </div> <div class="scroll-bar"> <!-- 滚动滑块 --> <div class="scroll-slider"></div> </div> </div> </div> </body> <script src="../JavaScript/jquery.min.js"></script> <script> (function (win, doc, $) { function CustomScrollBar(options) { this._init(options); } $.extend(CustomScrollBar.prototype, { // this -> CustomScrollBar _init: function (options) { let _this = this; _this.options = { scrollDir: 'y', //滚动方向 contentSelector: '', //滚动内容区选择器(样式带有overflow为hidden的) barSeletor: '', //滚动条选择器 sliderSelector: '', //滚水滑块选择器 wheelStep: 10 //滚轮步长 } $.extend(true, _this.options, options || {}); //深拷贝的方式合并两个对象 _this._initDomEvent(); return _this; }, _initSliderHeight: function () { let _this = this; let sliderHeight; let contentHeight = _this.$scrollContent.height(); let contentTotalHeight = _this.$scrollContent[0].scrollHeight; let offsetHeight = contentTotalHeight - contentHeight; if (offsetHeight <= 0) { sliderHeight = 0; } else { sliderHeight = contentHeight * contentHeight / contentTotalHeight } _this.$scrollSlider.height(`${sliderHeight}px`); return _this; }, _initDomEvent: function () { let opts = this.options; // 获取相应Jquery对象 this.$scrollContent = $(opts.contentSelector); this.$scrollSlider = $(opts.sliderSelector); this.$scrollBar = opts.barSeletor ? $(opts.barSeletor) : _this.$scrollSlider.parent(); this.$doc = $(doc); this._initSliderHeight(); //this._initSliderDragEvent(); this._bindMousewheel(); this._bindContentScroll(); }, _initSliderDragEvent: function () { let _this = this; let slider = _this.$scrollSlider; let sliderElement = slider[0]; if (sliderElement) { let doc = _this.$doc; let startScrollTop; let startPagePosition; let contentBarRate; function mousemoveHandler(sliderEvent) { event.preventDefault(); //判断是否按下鼠标 if (startPagePosition == null) { return; } // 内容可移动距离/滑块可移动距离 = 内容移动距离/滑块移动距离 let endPagePosition = sliderEvent.pageY let sliderMoveDistance = endPagePosition - startPagePosition; let contentMoveDistance = contentBarRate * sliderMoveDistance; let endScrollTop = startScrollTop + contentMoveDistance; _this.scrollTo(endScrollTop); } slider.on('mousedown', function (sliderEvent) { event.preventDefault(); startPagePosition = event.pageY; //clientY //获取可视区Top到移出可视区Top的距离 startScrollTop = _this.$scrollContent.scrollTop(); //获取内容可滚动高度与滑块可滚动高度比率 contentBarRate = _this.getContentMaxMovableDistance() / _this.getSliderMaxMovableDistance(); //.scroll命名空间,防止停止doc事件 doc.on('mousemove.scroll', mousemoveHandler) .on('mouseup.scroll', function () { doc.off('.scroll'); }) }); } return _this; }, //监听滚动内容,同步滑块位置 _bindContentScroll: function () { let _this = this; _this.$scrollContent.on('scroll', function () { let sliderElement = _this.$scrollSlider && _this.$scrollSlider[0]; if (sliderElement) { sliderElement.style.top = _this.getSliderPosition() + 'px'; } }) return _this; }, //监听滚轮事件 _bindMousewheel: function () { let _this = this; let scrollContent = _this.$scrollContent; scrollContent.bind('mousewheel DOMMouseScroll', function (contentEvent) { contentEvent.preventDefault(); let originEvent = contentEvent.originalEvent; //滚动幅度:wheelDelta 其他浏览器120, Firefox:3 let wheelRange = originEvent.wheelDelta ? -originEvent.wheelDelta / 120 : (originEvent.detail || 0) / 3; let startScrollTop = scrollContent.scrollTop(); let wheelMoveDistance = wheelRange * _this.options.wheelStep; _this.scrollTo(startScrollTop + wheelMoveDistance); }); return _this; }, //计算当前滑块位置 getSliderPosition: function () { let _this = this; // 滑块移动距离/滑块可移动距离 = 内容移动距离/内容可移动距离 let sliderMaxMovableDistance = _this.getSliderMaxMovableDistance(); let contentMaxMovableDistance = _this.getContentMaxMovableDistance(); let contentMoveDistance = _this.$scrollContent.scrollTop(); let sliderMoveDistance = sliderMaxMovableDistance * contentMoveDistance / contentMaxMovableDistance; return Math.min(sliderMaxMovableDistance, sliderMoveDistance) }, //获取内容可滚动高度 = 内容总高度 - 内容可视区高度 getContentMaxMovableDistance: function () { let _this = this; let contentHeight = _this.$scrollContent.height(); let contentTotalHeight = _this.$scrollContent[0].scrollHeight; return Math.max(contentHeight, contentTotalHeight) - contentHeight }, // 获取滑块可移动高度 = 滚动条高度 - 滑块高度 getSliderMaxMovableDistance: function () { let _this = this; let barHeight = _this.$scrollBar.height(); let sliderHeight = _this.$scrollSlider.height(); return barHeight - sliderHeight; }, scrollTo: function (endScrollTop) { let _this = this; _this.$scrollContent.scrollTop(endScrollTop); } }) win.CustomScrollBar = CustomScrollBar; })(window, document, jQuery) new CustomScrollBar({ contentSelector: '.scroll-content', barSeletor: '.scroll-bar', sliderSelector: '.scroll-slider' }) </script> </html>