九、多屬性同時運動
前面的例子都是每個屬性單獨運動,如果想要多屬性同時運動怎麼辦?例如,我想要一個div的onmouseover事件中寬和高同時變化。下面這個函數是單獨變寬:
window.onload=function(){ var ob1=document.getElementById('div1'); ob1.onmouseover=function(){ startMove(ob1,'width',400); } }
有一個想法就是在startMove下面再加一個startMove:
window.onload=function(){ var ob1=document.getElementById('div1'); ob1.onmouseover=function(){ startMove(ob1,'width',400); startMove(ob1,'height',400); } }
事實證明這種想法是錯誤的,這麼寫只有高變了,而寬沒變。為什麼呢?因為startMove函數的起初就是關閉定時器,當第一個startMove函數剛開始執行時,第二個startMove已經開始執行,第二個startMove的關閉定時器功能將第一個startMove的定時器覆蓋掉了,所以物體的寬無法變化,變的只有高。那麼如何解決?這裡要用到json:
var json={a:12,b:13}; for(var i in json){ alert(i); alert(json[i]); }
json裡的值是成對出現的,每一對為變數和變數的值。可以用for in迴圈來取得每一對的變數以及對應的值。上面程式依序彈出a,12,b,13 。
下面來看一下stareMove框架,發現參數裡的「屬性」和「目標值」是一對值,也就是說一個startMove只能實現一對值的變化。如何實現多對值的變化?來看看這個樣子的startMove :
startMove(obj,{attr1:target1,attr2:target2},fn),藍色部分就是json的形式,所以在原來的startMove基礎上,將藍色部分換成json ;將程式中的target換成json[attr](是哪個屬性,就是那個屬性的目標值)。改變完的startMove函數如下:(第1,4,13,16行做了改動)
function startMove(obj,json,fn) {//元素,改变的样式属性,达到的目标值,回调函数 clearInterval(obj.timer); obj.timer=setInterval(function(){ for(var attr in json){ //1.取当前值 var icur=0;//icur返回物体样式属性值的大小 if (attr=='opacity') {//如果属性是透明度,透明度的返回值是零点几的小数 icur=Math.round(parseFloat(getStyle(obj,attr))*100);//round函数避免透明度值在小数之间来回跳动 } else { icur=parseInt(getStyle(obj,attr)); } //2.算速度 var speed=(json[attr]-icur)/8;//分母为比例系数K,可调 speed=speed>0?Math.ceil(speed):Math.floor(speed);//缓冲速度要取整,不然移动不到终点就停止 //3.检测运动是否停止 if (icur==json[attr]) { clearInterval(obj.timer); if(fn){//上一个运动停止后判断一下是否还有下一个运动 fn(); } } else { if (attr=='opacity') { obj.style.filter='alpha(opacity:'+(icur+speed)+')';//IE浏览器 obj.style.opacity=(icur+speed)/100;//火狐浏览器 } else { obj.style[attr]=icur+speed+'px'; } } } },30) }
下面是一個div調用startMove函數達到寬高同時變化的效果:
<style type="text/css"> #div1{ width: 200px; height: 200px; background: red; border: 2px solid black; filter: alpha(opacity:30); opacity: 0.3; } </style>
<script type="text/javascript"> window.onload=function(){ var ob1=document.getElementById('div1'); ob1.onmouseover=function(){ startMove(ob1,{width:400,height:400});//json格式 } } </script>
可以再加一對透明度,實現寬、高、透明度同時變化:
<script type="text/javascript"> window.onload=function(){ var ob1=document.getElementById('div1'); ob1.onmouseover=function(){ startMove(ob1,{width:400,height:400,opacity:100}); } } </script>
本框架存在的問題:當我想要把寬變為201,高變為400,透明度變為100時,會出現一個問題:寬確實變成201,但是高和透明度還遠遠未達到目標值,運動就停止了。原因是17行的關閉定時器,原程式裡只要有一個屬性值達到目標值,就關閉定時器,並沒有對每個屬性是否達到目標值都做判斷。所以出現了當寬達到了目標值,高和透明度還沒達到目標值的時候定時器就關閉了。解決方法:我們需要判斷所有的屬性都達到目標值時才關閉定時器。 (第2行,第17行以後有改動)
function startMove(obj,json,fn) {//元素,改变的样式属性,达到的目标值,回调函数 var flag=true;//定义一个标杆,假设所有运动都达到了目标值 clearInterval(obj.timer); obj.timer=setInterval(function(){ for(var attr in json){ //1.取当前值 var icur=0;//icur返回物体样式属性值的大小 if (attr=='opacity') {//如果属性是透明度,透明度的返回值是零点几的小数 icur=Math.round(parseFloat(getStyle(obj,attr))*100);//round函数避免透明度值在小数之间来回跳动 } else { icur=parseInt(getStyle(obj,attr)); } //2.算速度 var speed=(json[attr]-icur)/8;//分母为比例系数K,可调 speed=speed>0?Math.ceil(speed):Math.floor(speed);//缓冲速度要取整,不然移动不到终点就停止 //3.检测运动是否停止 if (icur!=json[attr]) {//如果不是所有的运动都达到目标值 flag=false; } if (attr=='opacity') {//没达到目标值的继续运动 obj.style.filter='alpha(opacity:'+(icur+speed)+')';//IE浏览器 obj.style.opacity=(icur+speed)/100;//火狐浏览器 } else { obj.style[attr]=icur+speed+'px'; } if(flag){//如果所有的运动都达到了目标值,再关闭定时器,然后看看有没有链式运动 clearInterval(obj.timer); if(fn){ fn(); } } } },30) }
現在這個改動完的框架就是完美框架了,一些網站上常用的小動畫就可以用這個框架實現。
以上就是js動畫學習(五)的內容,更多相關內容請關注PHP中文網(www.php.cn)!