写了个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的。。