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的。。

  • 相关阅读:
    Eclipse安装反编译插件
    关于eclipse发送到桌面快捷方式后打不开
    字符串 242.有效的字符异位词
    栈 503.下一个更大的元素
    eclipse导入jar包
    Java获取当前的时间
    链表 24.两两交换链表中的节点
    链表 19.删除链表倒数第N个节点
    共享空间的栈
    栈的顺序存储结构
  • 原文地址:https://www.cnblogs.com/zhrj000/p/2963506.html
Copyright © 2011-2022 走看看