首頁  >  文章  >  web前端  >  js動畫學習(五)

js動畫學習(五)

黄舟
黄舟原創
2016-12-30 16:59:441274瀏覽

九、多屬性同時運動



前面的例子都是每個屬性單獨運動,如果想要多屬性同時運動怎麼辦?例如,我想要一個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(&#39;div1&#39;);
     ob1.onmouseover=function(){
         startMove(ob1,{width:400,height:400});//json格式
     }
 }    
 </script>

可以再加一對透明度,實現寬、高、透明度同時變化:

<script type="text/javascript">
 window.onload=function(){
     var ob1=document.getElementById(&#39;div1&#39;);
     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==&#39;opacity&#39;) {//如果属性是透明度,透明度的返回值是零点几的小数
                 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==&#39;opacity&#39;) {//没达到目标值的继续运动
                 obj.style.filter=&#39;alpha(opacity:&#39;+(icur+speed)+&#39;)&#39;;//IE浏览器
                 obj.style.opacity=(icur+speed)/100;//火狐浏览器
             } else {
                 obj.style[attr]=icur+speed+&#39;px&#39;;
             }
             
             if(flag){//如果所有的运动都达到了目标值,再关闭定时器,然后看看有没有链式运动
                 clearInterval(obj.timer);
                 if(fn){
                     fn();
                 }
             }
         }
             
     },30)
 }

現在這個改動完的框架就是完美框架了,一些網站上常用的小動畫就可以用這個框架實現。

以上就是js動畫學習(五)的內容,更多相關內容請關注PHP中文網(www.php.cn)!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn