效果图:
#案例:让盒子实现来链式运动
链式运动:是从一个动作运动到另一个动作,注意必须在动作执行完毕后才能进行下一个动作。
如果不判断fn的情况,那么盒子往下运动的时候会报错
#案例:使盒子执行完一系列动作,那么代码执行如下:
如果改为this(闭包),那么盒子不会完整执行一系列动作,它会停止。
停止的原因在于:执行的是fn函数(if(fn)fn();),因此需要使fn函数的this指向#当前对象(即让this指向136行的box节点,而box节点是152行的参数dom)
因此,让this指向dom,应写为:
#再作一个弹出,要求实现在完成一系列运动后再弹出一个弹窗
完整代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<style>
*{margin: 0;padding: 0;}
#box{
width: 200px;
height: 200px;
background: skyblue;
position: absolute;
left: 0;
top: 0;
opacity: 0.3;
filter: alpha(opacity:30);
}
</style>
<body>
<div id="box"></div>
<script>
var box = document.getElementById("box");
box.onmouseover = function(){
animate(this,700,"left",function(){
animate(this,500,"top",function(){
animate(this,0,"left",function(){
animate(this,0,"top",function(){
alert("完成");
});
});
});
});
}
function animate(dom,target,attr,fn){
//dom ===》DOM节点
//target ===》目标值
//attr ===》属性名称
//fn ===》回调函数
clearInterval(dom.timer);
dom.timer = setInterval(function(){
if(attr=="opacity"){
var objAttr= parseFloat(getAttr(dom,attr))*100;
}else{
var objAttr = parseInt(getAttr(dom,attr));
}
var speed = (target-objAttr)/10;
speed = speed>0 ?Math.ceil(speed):Math.floor(speed);
if(target == objAttr){
//停止定时器
clearInterval(dom.timer);//执行完毕
//由于第5行没有写参数fn(会报错),因此需要判断fn的情况
if(fn){
fn.call(dom);
}
}else{
if(attr=="opacity"){
dom.style.filter = "alpha(opacity:"+objAttr + speed+")";//IE
dom.style[attr] = (objAttr + speed)/100;
}else{
dom.style[attr] = objAttr + speed +"px";
}
}
},30)
}
function getAttr(dom,attr){
if(dom.currentStyle){
return dom.currentStyle[attr];
}else{
return getComputedStyle(dom,null)[attr];
}
}
</script>
</body>
</html>