js 自制滾動條


寫了個js自制滾動條,首先,先看一下demo(點擊這里) 先

有兩個demo,右邊那個黑色那個,是我一開始寫的比較膚淺的代碼:

var scrollself=(function(){

    var scrollblock, //滾動塊
        scrollcontent,  //被滾動的內容
        scrollbar,    //滾動條
        scrollpanel,    //滾動內容的滾動區域
        cdistance,  //滾動內容要滾動的距離
        bdistance,    //滾動塊要滾動的距離
        minuTop, //滾動條頭尾剩下的空白
        cTop,    //滾動內容的top
        startY=0,    //滾動動作開始初鼠標的位置
        bTop=0,    //滾動動作開始初滾動塊的top
        isDrag=false;  //是否拉動滾動塊


    function prevent(e){

        if(e.preventDefault){
            e.preventDefault();
        }
        if(e.stopPropagation){
            e.stopPropagation();
        }
        e.cancelBubble=true;
        e.returnValue=false;
    }

    function mouseDown(event){
        isDrag=true;
        event=event||window.event;
        startY=event.clientY;
        bTop=scrollblock.offsetTop;
        cTop=scrollcontent.offsetTop;

        // prevent(event);

    }

    function mouseMove(event){
        if(isDrag){

            event=event||window.event;
            
            var newbTop=event.clientY-startY+bTop,
                newcTop=cTop-(event.clientY-startY)/bdistance*cdistance;

            if(newbTop<minuTop){
                newbTop=minuTop;
                newcTop=0;
            }else{
                if(newbTop>bdistance+minuTop){
                    newcTop=-cdistance;
                    newbTop=bdistance+minuTop;
                }
            }

            scrollblock.style.top=newbTop+'px';
            scrollcontent.style.top=newcTop+'px';
        }else{
            isDrag=false;
        }

        // prevent(event);
    }

    function mouseUp(event){

        isDrag=false;

        // prevent(event);
    }

    function addHandler(){
        scrollblock.onmousedown=mouseDown;
        scrollblock.onmousemove=mouseMove;
        scrollblock.onmouseup=mouseUp;
        document.onmouseup=mouseUp;
    }


    return{
        init:function(scrollpanel_id,scrollcontent_id,scrollbar_id,scrollblock_id){
            scrollblock=document.getElementById(scrollblock_id);
            scrollcontent=document.getElementById(scrollcontent_id);
            scrollbar=document.getElementById(scrollbar_id);
            scrollpanel=document.getElementById(scrollpanel_id);
            minuTop=scrollblock.offsetTop;
            cdistance=scrollcontent.offsetHeight-scrollpanel.offsetHeight;
            bdistance=scrollbar.offsetHeight-minuTop*2-scrollblock.offsetHeight;
        
            enclose(scrollpanel,scrollcontent,scrollbar,scrollblock,bdistance,cdistance,minuTop);
            addHandler();
        }
    }


}());

scrollself.init('scrollpanel2','scrollcontent2','scrollbar2','scrollblock2');

 

之所以說它膚淺,比較一下兩個demo的滾動效果就知道了,右邊的快速拉動滾動塊時候,體驗效果好差,很卡,而左邊的就流暢多了。

因為很卡,我就又上網看了一下別人的代碼,然后把根據別人的思路把代碼改了一下,就有了左邊那個綠色的那個demo,很明顯,效果好了很多,代碼:

var scroll=(function(){

    var scrollblock, //滾動塊
        scrollcontent,  //被滾動的內容
        scrollbar,    //滾動條
        scrollpanel,    //滾動內容的滾動區域
        cdistance,  //滾動內容要滾動的距離
        bdistance,    //滾動塊要滾動的距離
        minuTop, //滾動條頭尾剩下的空白
        cTop,    //滾動內容的top
        startY=0,    //滾動動作開始初鼠標的位置
        bTop=0;    //滾動動作開始初滾動塊的top


    
    function mouseDown(event){
        event=event||window.event;
        startY=event.clientY;
        bTop=scrollblock.offsetTop;
        cTop=scrollcontent.offsetTop;
        // if(scrollblock.setCapture){
            
        //     scrollblock.onmousemove=doDrag;
        //     scrollblock.onmouseup=stopDrag;
        //     scrollblock.setCapture();
        // }else{
        //     document.addEventListener("mousemove",doDrag,true);
        //     document.addEventListener("mouseup",stopDrag,true);
        // }
        document.onmousemove=function(){
            doDrag();
        }
        document.onmouseup=function(){
            stopDrag();
        }
        document.getElementsByTagName('body')[0].onselectstart=function(){
            return false;
        }
        
    }

    function doDrag(event){
        event=event||window.event;
            
        var newbTop=event.clientY-startY+bTop,
            newcTop=cTop-(event.clientY-startY)/bdistance*cdistance;

        if(newbTop<minuTop){
            newbTop=minuTop;
            newcTop=0;
        }else if(newbTop>bdistance+minuTop){
            newcTop=-cdistance;
            newbTop=bdistance+minuTop;
        }
        scrollblock.style.top=newbTop+'px';
        scrollcontent.style.top=newcTop+'px';

    }

    function stopDrag(event){
        // if(scrollblock.releaseCapture){
        //     // scrollblock.onmousemove=doDrag;
        //     // scrollblock.onmouseup=stopDrag;
        //     scrollblock.releaseCapture();
        // }else{
        //     document.removeEventListener("mousemove",doDrag,true);
        //     document.removeEventListener("mouseup",stopDrag,true);
        // }
        document.onmousemove=null;
        document.onmouseup=null;

        document.getElementsByTagName('body')[0].onselectstart=function(){
            return true;
        };
    }


    return{
        init:function(scrollpanel_id,scrollcontent_id,scrollbar_id,scrollblock_id){
            scrollblock=document.getElementById(scrollblock_id);
            scrollcontent=document.getElementById(scrollcontent_id);
            scrollbar=document.getElementById(scrollbar_id);
            scrollpanel=document.getElementById(scrollpanel_id);
            minuTop=scrollblock.offsetTop;
            cdistance=scrollcontent.offsetHeight-scrollpanel.offsetHeight;
            bdistance=scrollbar.offsetHeight-minuTop*2-scrollblock.offsetHeight;


            scrollblock.onmousedown=mouseDown;
            enclose(scrollpanel,scrollcontent,scrollbar,scrollblock,bdistance,cdistance,minuTop);
        }
    }



}());

scroll.init('scrollpanel','scrollcontent','scrollbar','scrollblock');

 

 

 

(一開始錯誤的誤解:比較了一下兩個的代碼,其實修改的不多,就有一點很大的不同,流暢的那一個(左邊綠色那一個)多了這個東西——setCapture、releaseCapture。

具體是怎樣的,再研究一下先。

SetCapture()函數的說明為:“該函數在屬於當前線程的指定窗口里設置鼠標捕獲。一旦窗口捕獲了鼠標,所有鼠標輸入都針對該窗口,無論光標是否在窗口的邊界內。同一時刻只能有一個窗口捕獲鼠標。如果鼠標光標在另一個線程創建的窗口上,只有當鼠標鍵按下時系統才將鼠標輸入指向指定的窗口。”

綠色demo不卡是因為SetCapture()函數使得鼠標onmousemove的時候,即使鼠標離開了滾動塊,滾動塊仍可以捕獲得到onmousemove的消息,而黑色demo卡的原因就是因為鼠標離開了滾動塊,就捕獲不了了。)

囧啊,以上灰色部分真是不知所謂的誤解,后來再認真想一下其實沒那么復雜,只要在鼠標點擊滾動塊的時候把mousemove跟mouseup事件注冊到document里就行了,然后mouseup的時候事件解綁掉,所以把代碼給改了,其實沒有setCapture、releaseCapture也行的,而且這兩個東西是針對ie的。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM