zoukankan      html  css  js  c++  java
  • 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的。。

  • 相关阅读:
    51nod乘积之和
    Dell服务器安装OpenManage(OMSA)
    Nginx反向代理PHP
    搭建haproxy
    108. Convert Sorted Array to Binary Search Tree
    60. Permutation Sequence
    142. Linked List Cycle II
    129. Sum Root to Leaf Numbers
    118. Pascal's Triangle
    26. Remove Duplicates from Sorted Array
  • 原文地址:https://www.cnblogs.com/zhrj000/p/2963506.html
Copyright © 2011-2022 走看看