后来我们已经掌握了很多运动相关的知识,构建了自己的运动框架。 事实上,距离真正的完成版运动车架还有很远的距离。
链条运动框架
当我们解释链条运动框架时,我们需要解释什么是弹跳函数。 在我们之前的一个运动函数startMove中,如果我们再加一个参数,并且参数是一个函数,我们要在运动结束后调用这个函数——这就是所谓的回弹函数。
function startMove(obj, attr, iTarget, fnEnd){ clearInterval(obj.timer); obj.timer=setInterval(function (){ var cur=0; if(attr=='opacity') { cur=Math.round(parseFloat(getStyle(obj, attr))*100); } else { cur=parseInt(getStyle(obj, attr)); } var speed=(iTarget-cur)/6; speed=speed>0?Math.ceil(speed):Math.floor(speed); if(cur==iTarget) { clearInterval(obj.timer); if(fnEnd)fnEnd(); } else { if(attr=='opacity') { obj.style.filter='alpha(opacity:'+(cur+speed)+')'; obj.style.opacity=(cur+speed)/100; } else { obj.style[attr]=cur+speed+'px'; } } }, 30);};
在clearInterval之后javascript的定时器,我们调用这个函数(其实我们需要判断该函数是否传入)。
无标题文档 #div1 {width:100px; height:100px; background:red; filter:alpha(opacity:30); opacity:0.3;} window.onload=function () { var oDiv=document.getElementById('div1'); oDiv.onmouseover=function () { startMove(oDiv, 'width', 300, function (){ startMove(oDiv, 'height', 300, function (){ startMove(oDiv, 'opacity', 100); }); }); }; oDiv.onmouseout=function () { startMove(oDiv, 'opacity', 30, function (){ startMove(oDiv, 'height', 100, function (){ startMove(oDiv, 'width', 100); }); }); }; };
疗效如下:
可以看到,我们通过回弹函数的嵌套,实现了炫酷的拉伸效果——这就是一个简单的链条运动框架。
完美的运动框架
到目前为止,我们所学的运动框架仍然存在问题:
无标题文档 #div1 {width:100px; height:100px; background:red;} window.onload=function () { var oBtn=document.getElementById('btn1'); var oDiv=document.getElementById('div1'); oBtn.onclick=function () { startMove(oDiv, 'width', 300); startMove(oDiv, 'height', 300); }; };
疗效如下:
可以看到,我们试图同时改变div的宽度和高度,但最终只改变了高度。 原因是定时器两次调用该函数造成干扰,所以只有后面的startmove函数生效。 那么,我们目前的运动框架无法同时改变多个属性,我们应该如何解决呢? 答案是通过json。 json 的一个重要用法是循环 - 使用 forin。 以前我们通过两个参数传入属性和属性值。 现在我们直接传入一个jsonjavascript的定时器,将属性和属性值分别作为键值和通配符传入,这样就可以同时传入多组值了。
function startMove(obj, json, fnEnd){ clearInterval(obj.timer); obj.timer=setInterval(function (){ var bStop=true; //假设:所有值都已经到了 for(var attr in json) { var cur=0; if(attr=='opacity') { cur=Math.round(parseFloat(getStyle(obj, attr))*100); } else { cur=parseInt(getStyle(obj, attr)); } var speed=(json[attr]-cur)/6; speed=speed>0?Math.ceil(speed):Math.floor(speed); if(cur!=json[attr]) bStop=false; if(attr=='opacity') { obj.style.filter='alpha(opacity:'+(cur+speed)+')'; obj.style.opacity=(cur+speed)/100; } else { obj.style[attr]=cur+speed+'px'; } } if(bStop) { clearInterval(obj.timer); if(fnEnd)fnEnd(); } }, 30);}
通过json通配符对和forin循环,我们可以同时更改一个元素的多个属性。 这里注意,当属性值等于目标值时,原始运动帧就会停止,但是几个运动同时结束的时间并不相同——我们应该等到所有运动都结束后再关闭定时器,因此我们构建了一个 bStop 变量来确定所有运动是否都已到达终点。
无标题文档 #div1 {width:100px; height:100px; background:red; filter:alpha(opacity:30); opacity:0.3;} window.onload=function () { var oBtn=document.getElementById('btn1'); var oDiv=document.getElementById('div1'); oBtn.onclick=function () { startMove(oDiv, {width:101, height: 300, opacity: 100}, function (){ alert('a'); }); }; };
疗效如下:
这样,这个框架就可以同时改变元素的不同属性值(通过json实现),也可以分阶段改变属性值(通过bounce函数实现),从而形成一个比较完美的运动框架。 在css2的范围内,这个运动框架早就足够使用了。
至此,我们的练习框架已经基本讲清楚了。 以下是我们编制的练习框架的摘要:
发表评论