1. 程式人生 > >針對模擬滾動條插件(jQuery.slimscroll.js)的修改

針對模擬滾動條插件(jQuery.slimscroll.js)的修改

develop www. sele 覆蓋 瀏覽器 IE asc set css樣式

在開發過程中程序員總會碰到產品經理提出的各種稀奇古怪的需求,盡管有些需求很奇葩,但不得不說有些須有還是能指引我們不斷的學習與進步,最近在工作中就碰到這種問題。需求是要求在各主流瀏覽器上使用自定義的滾動條樣式,並且達到完美兼容,此篇博客記錄自己的分析過程。此篇博客的源碼可訪問slimscroll

為了能使用自定義的滾動條樣式並且能在各主流瀏覽器上兼容,首先想到的就是css定制滾動條的樣式。於是在網上搜索了下發現確實有這樣的css樣式存在:

ul::-webkit-scrollbar/*滾動條整體部分,其中的屬性有width,height,background,border(就和一個塊級元素一樣)等。*/
ul::-webkit-scrollbar-button /*滾動條兩端的按鈕。可以用display:none讓其不顯示,也可以添加背景圖片,顏色改變顯示效果。*/ ul::-webkit-scrollbar-track /* 外層軌道。可以用display:none讓其不顯示,也可以添加背景圖片,顏色改變顯示效果。*/ ul::-webkit-scrollbar-track-piece /*內層軌道,滾動條中間部分(除去)。*/ ul::-webkit-scrollbar-thumb /*滾動條裏面可以拖動的那部分*/ ul::-webkit-scrollbar-corner /* 邊角*/ ul::-webkit-resizer /*定義右下角拖動塊的樣式*/

這裏只是初略的介紹下,具體的使用方法可參考這篇博客自定義瀏覽器滾動條的樣式,打造屬於你的滾動條風格
這種方法確實可以定制滾動條樣式,但是僅僅是在webkit內核瀏覽器有效,不能達到完美兼容。上面的博客中推薦一種jquery插件來解決這個問題,但是介紹的並不全面,也不好使用。於是我在網上搜索了下發現類似的jquery插件有很多,為了更貼近項目需要我選擇了jquery.slimscroll.js. 可是在實際使用的過程中發現該插件不支持滾動的內容翻頁,一旦翻頁追加新內容,因為內容高度的變化導致存在滾動內容跳躍的情況。

重現問題

看實際效果請猛擊這裏demo1
從該插件的github上下載源碼,並引入到頁面中,為了看到效果請打開調試面板,我設置了在內容滾動時輸出其scrollTop值,根據輸出的結果我們可以很明顯的看到在追加新內容後,內容會有跳躍的情況

scrollTop 49
scrollTop 51
scrollTop 105   //內容向上跳躍了
scrollTop 108

打開源碼分析原因

源碼中的以下這段是在拖動滾動條時要觸發的函數

// make it draggable and no longer dependent on the jqueryUI
if (o.railDraggable){ //默認設置為true
  bar.bind("mousedown", function(e) {
    var $doc = $(document);
    isDragg = true;
    t = parseFloat(bar.css('top'));
    pageY = e.pageY;

    $doc.bind("mousemove.slimscroll", function(e){
      currTop = t + e.pageY - pageY;
      bar.css('top', currTop);
      scrollContent(0, bar.position().top, false);// scroll content
    });

    $doc.bind("mouseup.slimscroll", function(e) {
      isDragg = false;hideBar();
      $doc.unbind('.slimscroll');
    });
    return false;
  }).bind("selectstart.slimscroll", function(e){
    e.stopPropagation();
    e.preventDefault();
    return false;
  });
}

翻頁追加新內容的時候,我們需要重新初始化該插件,初始化的過程中會重新計算滾動條的top值,下拉翻頁時由於鼠標一直是按下的狀態,在追加新內容後t值和pageY值記錄的一直是按下狀態時刻(未追加新內容時刻)的。所以當追加完新內容後,再觸發mousemove事件時,currTop又會被計算得到翻頁之前的值(滾動條的top值也是之前的值了),而此時的內容高度已經變化了,所以內容會跳躍。(不知道有沒有解釋清楚啊)

針對問題的解決之道

通過上面的分析我們知道由於在翻頁追加新內容後未獲取到最新的滾動條的top值和最新的e.pageY值,針對這個問題我在源碼中添加了以下一些代碼:

// scroll content by the given offset
scrollContent(offset, false, true);

// 以下是我添加的內容
//追加新內容後強制解綁之前的鼠標事件,不使用翻頁之前記錄的值
$(document).unbind('mousemove.slimscroll');
//解綁後為了能繼續下拉滾動條,需重新綁定鼠標事件
//記錄最新的滾動條的top值和鼠標位置
var pageY, t = parseFloat(bar.css('top'));
$(document).bind("mousemove.slimscroll", function(e) {
    //這裏判斷鼠標狀態是為了區分滾動事件和拖動事件
    //當鼠標左鍵是按下狀態時,
    if (e.buttons == 1) {
        pageY = pageY || e.pageY
        currTop = t + e.pageY - pageY;
        bar.css('top', currTop);
        scrollContent(0, currTop, false); // scroll content
    }
    return;
})

以上代碼解決翻頁追加新內容後,拖動滾動條存在的跳躍問題

function _onWheel(e) {
    //... 
    var e = e || window.event;
    
    // 以下是我添加的內容
    //取消拖動
    $(document).unbind('mousemove.slimscroll');
    
    //...
}

以上這段代碼是為了解決翻頁滾動後的點擊事件被覆蓋問題

這裏為什麽用e.buttons而不用e.button?
MouseEvent.buttons 可指示任意鼠標事件中鼠標的按鍵情況
MouseEvent.button 只能夠表明在事件中通過按下或者放開一個按鍵,或者是多個按鍵同時按下時,哪一個按鍵被按下。因此,它對判斷mouseenter, mouseleave, mouseover, mouseout or mousemove這些事件並不可靠。

修改源碼之後的效果請猛擊這裏demo2

這裏修改的代碼僅僅是我一人之見,如果您有更好的方法,歡迎在評論中提出

參考文獻:

MouseEvent.button
MouseEvent.buttons

針對模擬滾動條插件(jQuery.slimscroll.js)的修改