九牛一毛-javascript居中侧边栏使用缓冲实现
一种实现侧边栏的方式很简单,就是用fixed定位方式实现。通过看视频学到了另一种,可以让其有移动感觉的方式,记录一下。
首先在右边居中建立一个区域,通过不断改变此区域上边距离整个网页顶部的距离来让其始终处在页面的一个位置上。即(当前显示页面的高度减去边栏区域的高度)除以二加上被卷去页面的高度,就是要求的top目标值。对于不同的网页标准可以通过document.documentElement(对应html标签)和document.body(对应body标签)获取这些信息如下:
- document.body.clientWidth:网页可见区域的宽度。
- document.body.clientHeight:网页可见区域的高度。
- document.body.offsetWidth:网页可见区域的宽度。(当对应body标签时包含边线,与clientWidth不同)。
- document.body.offsetHeight:网页可见区域的高度。(当对应body标签时包含边线,与clientHeight不同)。
- document.body.scrollWidth:网页正文全文宽度。(新浏览器不支持,与document.documentElement要一起使用,6.7.8.同)
- document.body.scrollHeight:网页正文全文高度。
- document.body.scrollTop:网页被卷去的高度。
- document.body.scrollLeft:网页被卷去的左边宽度。
为确保兼容性,使用document.documentElement.scrollTop||document.body.scrollTop的方式获得网页卷去的高度,初步实现想要的功能:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> #div1{ width:100px; height:150px; background-color:red; position:absolute; right:0; bottom:0px; } </style> <script> window.onscroll=function(){ var oDiv=document.getElementById('div1'); var scrollTop=document.documentElement.scrollTop||document.body.scrollTop; oDiv.style.top=(document.documentElement.clientHeight-oDiv.offsetHeight)/2+scrollTop+'px'; }; </script> </head> <body style="height:2000px"> <div id="div1"></div> </body> </html>
之后构建缓冲运动的函数。首先在函数外声明控制定时器的变量var timer=null;之所以要在函数外声明,是为了避免函数每执行一次,就创建一个timer变量。多个函数会创建多个timer,形成闭包,互相不共享,导致timer有很多个值,出现问题。
函数内部先获取div,var oDiv=document.getElementById('div1');之后清除上一次的定时器,并设定定时器。使移动的速度等于K倍的(offsetTop目标值减去offsetTop当前值),K<1。当速度大于0需要向上取整,小于0需要向下取整,防止速度绝对值不到1px时无法抵达目标位置的情况。之后做判断若当前值与目标位置一致就可以清除定时器,不一致就继续移动,移动函数:
function startMove(iTarget){
var oDiv=document.getElementById('div1');
clearInterval(timer);
timer=setInterval(function(){
var speed=(iTarget-oDiv.offsetTop)/10;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
if(oDiv.offsetTop==iTarget){
clearInterval(timer);
}
else{
oDiv.style.top=oDiv.offsetTop+speed+'px';
}
},30);
};
接下来把函数插入到卷屏时刻的函数就可以了。目标位置参数iTarget即oDiv.style.top,这里要注意'px'的存留与否。另外传入函数的参数有一个bug就是因为有/2的存在目标位置可能会有奇数的情况,但div移动只能以像素为单位,这就形成了要么与目标差0.5px,要么多出来0.5px,造成区域不断抖动。所以还需要对传入的参数进行parseInt计算确保是一个整数。合并后如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> #div1{ width:100px; height:150px; background-color:red; position:absolute; right:0; bottom:0px; } </style> <script> window.onscroll=function(){ var oDiv=document.getElementById('div1'); var scrollTop=document.documentElement.scrollTop||document.body.scrollTop; // oDiv.style.top=(document.documentElement.clientHeight-oDiv.offsetHeight)/2+scrollTop+'px'; startMove(parseInt((document.documentElement.clientHeight-oDiv.offsetHeight)/2+scrollTop)); }; var timer=null; function startMove(iTarget){ var oDiv=document.getElementById('div1'); clearInterval(timer); timer=setInterval(function(){ var speed=(iTarget-oDiv.offsetTop)/10; speed=speed>0?Math.ceil(speed):Math.floor(speed); if(oDiv.offsetTop==iTarget){ clearInterval(timer); } else{ oDiv.style.top=oDiv.offsetTop+speed+'px'; } },30); }; </script> </head> <body style="height:2000px"> <div id="div1"></div> </body> </html>