之前写了几篇JS动画实现了缓冲运动,改变宽,高,透明度的效果,但是这些动画效果都没有同时作用于某一个元素,譬如,想要实现一个DIV元素先变宽,再变高,最后透明度再来个变化,也就是链式运动,这该如何实现呢,又譬如,想要一个DIV元素在鼠标移入时,它的宽高透明度同时改变,这又该如何实现呢。
先解决第一个问题,链式运动。
将所有的动画运动效果封装成在一起,取名为move.js.可见,链式的实现在于添加第四个参数乐趣,用来调用下一个动画函数。
function getStyle(obj,attr){
if(obj.currentStyle){
return obj.currentStyle[attr];
}else{
return getComputedStyle(obj,false)[attr];
}
}
function startMove(obj,attr,iTarget,fun){
clearInterval(obj.timer);
obj.timer=setInterval(function(){
// 取当前值
var icur=0;
if(attr == "opacity"){
icur=parseFloat(getStyle(obj,attr))*100;
}else{
icur=parseInt(getStyle(obj,attr));
}
// 计算速度
var speed=(iTarget-icur)/8;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
// 检测停止
if(icur == iTarget){
clearInterval(obj.timer);
if(fun){ //当存在第四个参数fun时,调用这个fun函数
fun();
}
}else{
if(attr == "opacity"){
obj.style.filter="alpha(opacity=)"+(icur+speed)+")";
obj.style.opacity=(icur+speed)/100;
}else{
obj.style[attr] = icur+speed+"px";
}
}
},30)
}
链式运动主体部分。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>链式运动</title>
<style>
div{width: 200px;height: 100px;border: 1px solid black;background: red;filter: alpha(opacity=30);opacity: 0.3;}
</style>
<script src="move.js"></script>
<script>
window.onload=function(){
var oDiv=document.getElementById("div");
oDiv.onmouseover=function(){
startMove(oDiv,"width",400,function(){
startMove(oDiv,"height",200,function(){
startMove(oDiv,"opacity",100);
})
})
};
oDiv.onmouseout=function(){
startMove(oDiv,"opacity",30,function(){
startMove(oDiv,"height",100,function(){
startMove(oDiv,"width",200);
})
})
}
}
</script>
</head>
<body>
<div id="div"></div>
</body>
</html>
其中链式实现的部分:
第二个问题,多物体同时运动。
这个问题是否可以沿用上面的方法就能够解决呢,先假设同时运动就同时调用stratMove函数,然而这样是不行的,后一个函数会覆盖前一个,无法做到多种运动的同时进行。
这个问题的解决要涉及到 json。json的定义格式和遍历方法:
var json={name:bert,age:24,score:100}; //name:key
for(var i in json){
alert(i); //name
alert(json[i]); //key
}
根据json的格式,我们需要来改造一下 move.js 。json的格式是一对 name:key 值,看一下move.js
attr就是json中的name,iTarget是key。想要实现同时运动,那move.js 中三步骤:取当前值、计算速度、检测停止,json中的每一个对值都去完成这三步骤,不就是同时运动嘛。
修改的move.js部分:
那么相应部分调用startMove函数,修改成:
var oDiv=document.getElementById("div");
oDiv.onmouseover=function(){
startMove(oDiv,{width:400,height:200,opacity:100});
}
oDiv.onmouseout=function(){
startMove(oDiv,{width:200,height:100,opacity:30});
}
存在的bug
当我们修改需要改变的宽度为205或者其他较小的值,测试发现,当宽度达到目标值之后,height和opacity的值也会停止,无法增长到目标值。这是因为在三步骤中的 “检测停止” 中,我们并没有做一个判断,是否所有属性值都达到了目标值。修改如下: