jquery: 自定义滚动优化
(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的) sliderSelector: '', //滚水滑块选择器 barSeletor: '', //滚动条选择器 wheelStep: 10 //滚轮步长 } $.extend(true, _this.options, options || {}); //深拷贝的方式合并两个对象 _this._initDomEvent(); 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(); }, _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; _this._unbindMouseOver(); } else { sliderHeight = contentHeight * contentHeight / contentTotalHeight; _this._bindMouseHover(); } _this.$scrollSlider.height(`${sliderHeight}px`); return _this; }, _unbindMouseOver: function () { this.$scrollBar.hide(); this.$scrollContent.off('mouseenter mouseleave'); }, _bindMouseHover: function () { let _this = this; this.$scrollContent.on({ mouseenter: function () { _this.$scrollBar.show(); }, mouseleave: function () { _this.$scrollBar.hide(); } }) }, _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) { sliderEvent.preventDefault(); startPagePosition = sliderEvent.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); // 根据不同类型获取滚动实例 function getCustomScrollBarInstance(tagId) { let params = { contentSelector: `#${tagId} .scroll-content`, sliderSelector: `#${tagId} .scroll-slider`, barSeletor: `#${tagId} .scroll-bar`, wheelStep: 20 } return new CustomScrollBar(params); }