1.前言
在一些网页中,经常可以看到边框上,有一个“分享到”的小标签,鼠标进入后,划出一个小框,上面是微信、QQ等选项。这个效果可以使用js运动来实现。
尽管在现实开发中,运动可能大都使用 jQuery 等框架来完成,但是生js编码还是要熟悉一下。
在学习过程中,看着挺简单的,结果是脑子会了,自己做得时候手没跟上(主要是布局方面),所以即使看起来简单的东西还是要自己做自己积累。
2. 运动原理
一般情况下,可通过设置元素的一些属性,如长宽高、边框、位置、透明度等,达到运动的效果。
当需要匀速或变速运动时,只需要使用定时器逐次增加或减少即可。
3. sidebar初试
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>sidebar</title>
<style>
#div1 {width:150px; height:200px; left:-150px; position:absolute; background-color:red;}
#div1 span {position:absolute; width:20px; height:100px; line-height:20px; right:-20px; top:70px; background-color:green;}
</style>
<script>
window.onload = function(){
var oDiv = document.getElementById("div1");
//注意,使用的div来作为监听对象,而不是span。span范围很小,不利于鼠标移入移出,
//会造成抖动
oDiv.onmouseover = function(){
oDiv.style.left = 0 + "px";
};
oDiv.onmouseout = function(){
oDiv.style.left = -150 + "px";
};
}
</script>
</head>
<body>
<div id="div1">
<span>分享到</span>
</div>
</body>
</html>
大致效果如下。
关于布局,慢慢弄懂了一些东西:
1.div1的长、宽都为100px,为了程序刚运行的时候不可见,所以设置绝对定位,left为-100px。
2.span为div1的子元素,且为绝对定位。line-height指定行高,也即“分享到”这三个字每个字的垂直距离。关于right:-20px
这点想了很久才想明白。绝对定位相对于已经定位过的祖先元素(找到为止,父元素没有定位则找父元素的父元素,直到相对于文档本身)。详细说明如下。
<style>
#div1 {width:150px; height:200px; left:-150px; position:absolute; background-color:red;}
#div1 span {position:absolute; width:20px; height:100px; line-height:20px; left:150px; top:70px; background-color:green;}
</style>
把right:-20px修改成left:150px是一样的结果。
经过系列摸索,得到结论如下(图中的数据为说明用,与上方测试数据不一)。
4.匀速
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>sidebar</title>
<style>
#div1 {width:150px; height:200px; left:-150px; position:absolute; background-color:red;}
#div1 span {position:absolute; width:20px; height:100px; line-height:20px; right:-20px; top:70px; background-color:green;}
</style>
<script>
var timer = null;
window.onload = function(){
var oDiv = document.getElementById("div1");
oDiv.onmouseover = function(){
//oDiv.style.left = 0 + "px";
moveTo(oDiv, 0 )
};
oDiv.onmouseout = function(){
//oDiv.style.left = -150 + "px";
moveTo(oDiv, -150 )
};
}
function moveTo(obj, iTarget){
var speed;
clearInterval(timer);
if(obj.offsetLeft>iTarget)
speed = -10;
else
speed =10;
timer = setInterval(function(){
if(obj.offsetLeft == iTarget)
clearInterval(timer);
else
obj.style.left = obj.offsetLeft + speed + "px";
},30);
}
</script>
</head>
<body>
<div id="div1">
<span>分享到</span>
</div>
</body>
</html>
1.为了重复使用代码,所以封装了函数
2.为了每次鼠标进入移除之间不互相干扰引发错误,每次实际运动前现将定时器关闭。
3.匀速运动过程中会遇到一个问题,即当距离不能被速度整除的话,整个运动可能会一直持续,而非到点停止。例如,本例中,当speed=7时,因为距离为150px,后者不能被前者整除,会出现下图这种情况,可以看到,left已经完全脱离0点。
可行的一种解决办法是,告诉浏览器,在一定范围内就算到了,加上whenArrival函数,如下。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<style>
#div1 {width:150px; height:200px; left:-150px; position:absolute; background-color:red;}
#div1 span {position:absolute; width:20px; height:100px; line-height:20px; right:-20px; top:70px; background-color:green;}
</style>
<script>
var timer = null;
window.onload = function(){
var oDiv = document.getElementById("div1");
oDiv.onmouseover = function(){
//oDiv.style.left = 0 + "px";
moveTo(oDiv, 0 )
};
oDiv.onmouseout = function(){
//oDiv.style.left = -150 + "px";
moveTo(oDiv, -150 )
};
}
function moveTo(obj, iTarget){
var speed;
clearInterval(timer);
if(obj.offsetLeft>iTarget)
speed = -7;
else
speed = 7;
timer = setInterval(function(){
/*if(obj.offsetLeft == iTarget)
clearInterval(timer);
else
obj.style.left = obj.offsetLeft + speed + "px"; */
whenArrival(obj, iTarget, speed);
},30);
}
function whenArrival(obj, iTarget, speed){
if(Math.abs(obj.offsetLeft - iTarget) <= Math.abs(speed)){
clearInterval(timer);
obj.style.left = iTarget + "px";
}else{
obj.style.left = obj.offsetLeft + speed + "px";
}
}
</script>
</head>
<body>
<div id="div1">
<span>分享到</span>
</div>
</body>
</html>
whenArrival函数中,需要注意的是,Math.abs中Math是大写的;另外,
obj.style.left = iTarget + "px";
和
obj.style.left = obj.offsetLeft + speed + "px";
后面的px单位不能忘。
5.缓动
缓动,也即速度与距离成正比,只需将原先定死的速度写成灵活的,如下:
speed = (obj.offsetLeft - iTarget)/ 7;
但是,这个方法还有一个问题。最小单位是1px,经上式算出来的速度,出现小数是不可避免的,这就要用到向上取整或者向下取整了。
speed=speed>0?Math.ceil(speed):Math.floor(speed);
不需要用到whenArrival函数。因为缓动时速度可变,最后速度取整总会能出现1。
function moveTo(obj, iTarget){
var speed;
clearInterval(timer);
speed = (iTarget-obj.offsetLeft)/7;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
timer = setInterval(function(){
if(obj.offsetLeft == iTarget)
clearInterval(timer);
else
obj.style.left = obj.offsetLeft + speed + “px”;
},30);
}
缓动还存在一个隐藏的问题。因为目标值有可能是计算所得,所以目标值也存在不是整数的情况。又因为最小单位为1像素,所以当出现这种情况时,需要使用 parseInt 函数对目标值取整。这将到位的元素与实际需要达到的元素存在些许差别。
6.总结
内容比较简单,但重在积累,加油!
1.运动的思想:属性改变
2.匀速运动思想:速度恒定
3.缓动思想:速度随着距离改变
4.缓动中速度取整、匀速中到达目标点的判断很重要,处理运动时,这方面思想不能少
5.开发中比较容易遗漏单位,应仔细检查,否则无法达到预期效果,且不会报错。
6.关于布局方面的知识应当加强。