1. 程式人生 > 實用技巧 >jquery: 自定義滾動優化

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); }