JavaScript 运动框架 Step by step

来源:互联网 发布:oracle数据库接口 编辑:程序博客网 时间:2024/05/29 06:42

1,运动原理

Js运动,本质来说,就是让 web 上 DOM 元素动起来。而想要 DOM 动起来,改变其自身的位置属性,比如高宽,左边距,上边距,透明度等。动画的原理就是把不同状态的物体,串成连续的样子,就像一本书,画了几个小人,然后一翻书,就看见小人在动。js动画也一样。不同状态的DOM,用定时器控制,就能得到动画效果。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var oBtn = document.getElementById('btn');  
  3.     oBtn.onclick = function(){  
  4.         var oDiv = document.getElementById('div1');  
  5.         //设置定时器  
  6.         setInterval(function(){  
  7.             //改变物体位置  
  8.             oDiv.style.left = oDiv.offsetLeft + 10 + 'px';  
  9.         },30)  
  10.                                                                                                                                                                                                                                                                       
  11.     }  
  12. }  

上述代码,点击btn之后,就能是物体向左运动。可是会一直向右动,不会停止。因此需要创立一个停止的条件。在条件符合的情况下,清楚定时器。其中对于目标点的判断,尤为重要。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var oBtn = document.getElementById('btn');  
  3.     oBtn.onclick = function(){  
  4.         var oDiv = document.getElementById('div1');  
  5.         //设置定时器  
  6.         var timer = setInterval(function(){  
  7.             //判断停止条件  
  8.             if(oDiv.offsetLeft > 300){  
  9.                 clearInterval(timer);  
  10.             }else{  
  11.                 //改变物体位置  
  12.                 oDiv.style.left = oDiv.offsetLeft + 10 + 'px';  
  13.                 document.title = oDiv.offsetLeft;  
  14.             }  
  15.         },30);  
  16.                                                                                                                                                                                                                                                            
  17.     }  
  18. }  

上述代码中,但物体的位置大于300的时候,将停止运动。但是上述代码还有个问题,就是连续点击按钮,物体会运动越来越快。因为每点击一次,就开了一个定时器,累加的定时器。造成运动混乱。

2,运动框架 (滑入出,淡入淡出)

为了解决上述问题,则必须在开启定时器之前,先清除定时器,因此需要一个全局变量 timer保存定时器。如下面代码。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var oBtn = document.getElementById('btn');  
  3.     oBtn.onclick = function(){  
  4.         startMove();  
  5.     }  
  6. }  
  7. var timer = null;  
  8. function startMove(){  
  9.     var oDiv = document.getElementById('div1');  
  10.     clearInterval(timer);  
  11.     //设置定时器  
  12.     timer = setInterval(function(){  
  13.         //判断停止条件  
  14.         if(oDiv.offsetLeft > 300){  
  15.             clearInterval(timer);  
  16.         }else{  
  17.             //改变物体位置  
  18.             oDiv.style.left = oDiv.offsetLeft + 10 + 'px';  
  19.             document.title = oDiv.offsetLeft;  
  20.         }  
  21.     },30);  
  22. }  

此外,在改变物体位置的时候,那个 “10”则是更改的数量,其实也就是速度。如果更改速度,运动的快慢就能确定。因此,运动框架的原理,基本步骤为。

  • 先清除定时器

  • 开启定时器,计算速度

  • 判断停止条件,执行运动

[javascript] view plain copy
  1. var timer = null;  
  2. function startMove(){  
  3.     var oDiv = document.getElementById('div1');  
  4.     clearInterval(timer);  
  5.         //计算速度  
  6.     var iSpeed = 10;  
  7.     //设置定时器  
  8.     timer = setInterval(function(){  
  9.         //判断停止条件  
  10.         if(oDiv.offsetLeft > 300){  
  11.             clearInterval(timer);  
  12.         }else{  
  13.             //改变物体位置  
  14.             oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';  
  15.             document.title = oDiv.offsetLeft;  
  16.         }  
  17.     },30);  
  18. }  

对于停止条件,写死在里面了,所以需分离出参数。下面是一个分享到的例子。主要是根据目标判断速度的正负。从而在鼠标滑入画出时候进行运动/恢复的效果。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var oDiv = document.getElementById('div1');  
  3.     oDiv.onmouseover = function(){  
  4.         startMove(0);  
  5.     }  
  6.     oDiv.onmouseout = function(){  
  7.         startMove(-100);  
  8.     }  
  9. }  
  10. var timer = null;  
  11. var iSpeed;  
  12. function startMove(iTatget){  
  13.     var oDiv = document.getElementById('div1');  
  14.     clearInterval(timer);  
  15.     timer = setInterval(function(){  
  16.         //计算速度  
  17.         if(iTatget -oDiv.offsetLeft > 0){  
  18.             iSpeed = 10;  
  19.         }else{  
  20.             iSpeed = -10;  
  21.         }  
  22.                                                                                                                                                                                                                                
  23.         if(oDiv.offsetLeft == iTatget){  
  24.             clearInterval(timer);  
  25.         }else{  
  26.             oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';  
  27.         }  
  28.         document.title = oDiv.offsetLeft;  
  29.     },30)  
  30. }  

另外一个小例子,淡入淡出,即改变物体的透明度,由于没有像原生的位置属性那样的offsetLset. 需要一个变量来保存透明度的值,用来和速度加减,最后付给元素的透明度样式。从而实现淡入淡出效果。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var oImg = document.getElementById('img1');  
  3.     oImg.onmouseover = function(){  
  4.         startMove(100);  
  5.     }  
  6.     oImg.onmouseout = function(){  
  7.         startMove(30);  
  8.     }  
  9. }  
  10. var timer = null;  
  11. //保存透明度的数字值  
  12. var alpha = 30;  
  13. function startMove(iTarget){  
  14.     var oDiv = document.getElementById('img1');  
  15.     clearInterval(timer);  
  16.     timer = setInterval(function(){  
  17.         var iSpeed = 0;  
  18.         if(alpha > iTarget){  
  19.             iSpeed = -1;  
  20.         }else{  
  21.             iSpeed = 1;  
  22.         }  
  23.         if(alpha == iTarget){  
  24.             clearInterval(timer);  
  25.         }else{  
  26.                         //改变透明度速度值  
  27.             alpha += iSpeed;  
  28.             oDiv.style.filter = 'alpha(opacity:'+ alpha+')';  
  29.             oDiv.style.opacity = alpha/100;  
  30.             document.title = alpha;  
  31.         }  
  32.                                                                                                                                                                                                          
  33.     },30)  
  34. }  

3,缓冲运动

缓冲运动原理就是,改变速度的值。每次累加的速度值变小,就是会是整个物体看起来越来越慢,以至于最后停掉。相当于改变使物体具有一个加速度。这个加速度,可以由物体当前位置和目标位置之间的距离得到,因为两者之间的距离一直在变小,所以速度也一直在变小。如下:

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var btn = document.getElementsByTagName('input')[0];  
  3.     btn.onclick = function(){  
  4.         startMove(300);  
  5.     }  
  6. }  
  7. var timer = null;  
  8. function startMove(iTarget){  
  9.     var oDiv = document.getElementById('div1');  
  10.     clearInterval(timer);  
  11.     timer = setInterval(function(){  
  12.         //求出带有变化的速度   
  13.         var iSpeed = (iTarget - oDiv.offsetLeft) / 8;  
  14.         if(oDiv.offsetLeft == iTarget){  
  15.             clearInterval(timer);  
  16.         }else{  
  17.             oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';  
  18.         }  
  19.         document.title = oDiv.offsetLeft + '...' + iSpeed;  
  20.     },30);  
  21. }  

上述方法可以得到缓冲运动,但是实际运行效果,物体并没有在 300的位置停掉,而是在 293的位置就停掉了。究其原因。因为当物体的速度小于1 的时候。物体位置为293。此时计算的速度是 0.875.通过 oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px'; 物体的位置为 293.875.可是计算机不能识别小数,将小数省略了。此时的 位置offsetLeft仍然是 293.再计算一次,还是同样的结果。定时器没有关掉,但是物体的位置却再也无法改变,故停留在了 293的位置。解决方案,就是将速度进行向上取整。但是,像上述运动,速度是正的,可是,当速度是负的时候,就同样会有相同的结果,因此需要在速度为负的时候,向下取整。

[javascript] view plain copy
  1. function startMove(iTarget){  
  2.     var oDiv = document.getElementById('div1');  
  3.     clearInterval(timer);  
  4.     timer = setInterval(function(){  
  5.         var iSpeed = (iTarget - oDiv.offsetLeft) / 8;  
  6.         //对正的速度向上取整,负的速度向下取整  
  7.         iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);  
  8.         if(oDiv.offsetLeft == iTarget){  
  9.             clearInterval(timer);  
  10.         }else{  
  11.             oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';  
  12.         }  
  13.         document.title = oDiv.offsetLeft + '...' + iSpeed;  
  14.     },30);  
  15. }  

4.多物体运动

下一步,就是处理多物体运动,运动函数里面每次都要选取一个元素加事件。如果需要对多个物体进行同样的运动, 需要将运动对象作为参数传进来。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var aDiv = document.getElementsByTagName('div');  
  3.     for(var i=0;i<aDiv.length;i++){  
  4.         aDiv[i].onmouseover = function(){  
  5.             startMove(this,300);  
  6.         }  
  7.         aDiv[i].onmouseout = function(){  
  8.             startMove(this,100);  
  9.         }  
  10.     }  
  11. }  
  12. var timer = null;  
  13. function startMove(obj,iTarget){  
  14.     clearInterval(timer);  
  15.     timer = setInterval(function(){  
  16.         var iSpeed = (iTarget - obj.offsetWidth) / 8;  
  17.         iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);  
  18.         if(obj.offsetWidth == iTarget){  
  19.             clearInterval(timer);  
  20.         }else{  
  21.             obj.style.width = obj.offsetWidth + iSpeed + 'px';  
  22.         }  
  23.                                                                                                                                                          
  24.     },30)  
  25. }  

通过循环物体,将物体的 this传给运动函数,使得多物体可以运动。但是这样有一个弊端,即当滑入第一个运动的时候,开启了定时器。如果此时,滑入另外一个物体,将会清理上一个定时器。这就造成了,上一次运动,很有可能还没完成结束,定时器就没关闭了。解决的方法,每个运动的物体,都能开了一个属于自己的定时器。因此,把定时器当成物体的属性。清理的时候也就是清理自己的定时器。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var aDiv = document.getElementsByTagName('div');  
  3.     for(var i=0;i<aDiv.length;i++){  
  4.         aDiv[i].onmouseover = function(){  
  5.             startMove(this,300);  
  6.         }  
  7.         aDiv[i].onmouseout = function(){  
  8.             startMove(this,100);  
  9.         }  
  10.     }  
  11. }  
  12. function startMove(obj,iTarget){  
  13.     //将定时器,变成物体的属性,类似给物体添加索引  
  14.     clearInterval(obj.timer);  
  15.     obj.timer = setInterval(function(){  
  16.         var iSpeed = (iTarget - obj.offsetWidth) / 8;  
  17.         iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);  
  18.         if(obj.offsetWidth == iTarget){  
  19.             clearInterval(obj.timer);  
  20.         }else{  
  21.             obj.style.width = obj.offsetWidth + iSpeed + 'px';  
  22.         }  
  23.                                                                                                                                              
  24.     },30)  
  25. }  

多物体的淡入淡出的时候,也有类似的问题。因为修改透明度的时候,是先用一个变量保存透明度,必须针对每个物体设立透明度值属性。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var aDiv = document.getElementsByTagName('div');  
  3.     for(var i=0;i<aDiv.length;i++){  
  4.         //将透明度值当初属性  
  5.         aDiv[i].alpha = 30;  
  6.         aDiv[i].onmouseover = function(){  
  7.             startMove(this,100);  
  8.         }  
  9.         aDiv[i].onmouseout = function(){  
  10.             startMove(this,30);  
  11.         }  
  12.     }  
  13. }  
  14. function startMove(obj,iTarget){      
  15.     clearInterval(obj.timer);  
  16.     obj.timer = setInterval(function(){  
  17.         var iSpeed = (iTarget - obj.alpha) / 8;  
  18.         iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);  
  19.         if(obj.alpha == iTarget){  
  20.             clearInterval(obj.timer);  
  21.         }else{  
  22.             obj.alpha += iSpeed;  
  23.             obj.style.filter = 'alpha(opacity:'+obj.alpha+')';  
  24.             obj.style.opacity = obj.alpha / 100;  
  25.         }  
  26.         document.title = obj.alpha;  
  27.     },30);  
  28. }  

4.1  位置属性的bug

offsetWidth 或者 offsetHeight 等位置属性,一旦给他们加上 border。则会有诡异的现象出现。

[javascript] view plain copy
  1. window.onload = function(){  
  2.         var oDiv = document.getElementById('div1');  
  3.         setInterval(function(){  
  4.             oDiv.style.width = oDiv.offsetWidth - 1 + "px";  
  5.         },30)  
  6.     }  

例如 oDiv.style.width = oDiv.offsetWidth - 1 + 'px'; 如果给 oDiv 的width 为一百,border 为 1.则这个物体的 width是100px;offsetWidth 为102px;带入公式之后,即减一之后。100 = 102 - 1 ,反而等于101;即 物体本来要减小,事实却增大了。解决的方案就是,加减的时候,必须使用物体的内联样式。但是 火狐 和 IE 又有兼容模式。解决方案如下:

[javascript] view plain copy
  1. window.onload = function(){  
  2.         var oDiv = document.getElementById('div1');  
  3.         setInterval(function(){  
  4.                                                                                                                    
  5.             oDiv.style.width = parseInt(getStyle(oDiv,'width')) - 1 + 'px';  
  6.                                                                                                         
  7.         },30)  
  8.     }  
  9.     function getStyle(obj,attr){  
  10.         if(obj.currentStyle){  
  11.             return obj.currentStyle[attr];  
  12.         }else{  
  13.             return getComputedStyle(obj,false)[attr];  
  14.         }  
  15.     }  

其中,getStyle函数,传入一个元素对象,和其 css 属性,获取的是元素的样式,即 witdh 100px;因此需要parseInt转换

5.任意值运动

通过 getStyle 函数,可以获取元素的样式,还可也通过 attr 制定需要修改的 css属性。这样就能是物体有不同的运动形式。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var aDiv = document.getElementsByTagName('div');  
  3.     aDiv[0].onmouseover = function(){  
  4.         startMove(this,'width',300);  
  5.     }  
  6.     aDiv[0].onmouseout = function(){  
  7.         startMove(this,'width',100);  
  8.     }  
  9.     aDiv[1].onmouseover = function(){  
  10.         startMove(this,'height',100);  
  11.     }  
  12.     aDiv[1].onmouseout = function(){  
  13.         startMove(this,'height',50);  
  14.     }  
  15. }  
  16. function getStyle(obj,attr){  
  17.     if(obj.currentStyle){  
  18.         return obj.currentStyle(attr);  
  19.     }else{  
  20.         return getComputedStyle(obj,false)[attr];  
  21.     }  
  22. }  
  23. function startMove(obj,attr,iTarget){  
  24.     clearInterval(obj.timer);  
  25.     obj.timer = setInterval(function(){  
  26.         var iCur = parseInt(getStyle(obj,attr));  
  27.         var iSpeed = (iTarget - iCur) / 8;  
  28.         iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);  
  29.         if(iCur == iTarget){  
  30.             clearInterval(obj.timer);  
  31.         }else{  
  32.             obj.style[attr] = iCur + iSpeed + 'px';  
  33.         }  
  34.                                                                                                     
  35.     },30)  
  36. }  

5.1 任意值完美版

上述版本,还不能处理透明度的任意值,因此需要增加额外的兼容hack。

[javascript] view plain copy
  1. window.onload = function(){  
  2.         var aDiv = document.getElementsByTagName('div');  
  3.         aDiv[0].onmouseover = function(){  
  4.             startMove(this,'opacity',100);  
  5.         }  
  6.         aDiv[0].onmouseout = function(){  
  7.             startMove(this,'opacity',30);  
  8.         }  
  9.     }  
  10.     function getStyle(obj,attr){  
  11.         if(obj.currentStyle){  
  12.             return obj.currentStyleattr[attr];  
  13.         }else{  
  14.             return getComputedStyle(obj, false)[attr];  
  15.         }  
  16.     }  
  17.     function getStyle(obj, attr){  
  18.         if(obj.currentStyle)    {  
  19.             return obj.currentStyle[attr];  
  20.         }else{  
  21.             return getComputedStyle(obj, false)[attr];  
  22.         }  
  23.     }  
  24.     function startMove(obj,attr,iTarget){  
  25.         clearInterval(obj.timer);  
  26.         obj.timer = setInterval(function(){  
  27.             var iCur = 0;  
  28.             if(attr == 'opacity'){  
  29.                 iCur = parseInt(parseFloat(getStyle(obj, attr))*100);  
  30.             }else{  
  31.                 iCur = parseInt(getStyle(obj,attr));  
  32.             }  
  33.             var iSpeed = (iTarget - iCur) / 8;  
  34.             iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);  
  35.             if(iCur == iTarget){  
  36.                 clearInterval(obj.timer);  
  37.             }else{  
  38.                 if(attr=='opacity'){  
  39.                     iCur += iSpeed  
  40.                     obj.style.filter='alpha(opacity:' + iCur + ')';  
  41.                     obj.style.opacity=iCur / 100;  
  42.                 }  
  43.                 else{  
  44.                     obj.style[attr]=iCur+iSpeed+'px';  
  45.                 }  
  46.                 document.title = obj.style[attr];  
  47.             }  
  48.                                                                                       
  49.         },30)  
  50.     }  

6.链式运动

我们的运动框架到目前为止,基本功能都能实现了。现在拓展。所谓链式运动,即运动接着运动。当运动停止的时候,如果回调一个函数。回调一个运动函数,就能出现这样的效果。因此传入一个函数作为回调函数。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var oDiv = document.getElementById('div1');  
  3.     oDiv.onclick = function(){  
  4.         startMove(this,'width',300,function(){  
  5.             startMove(oDiv,'height',300,function(){  
  6.                 startMove(oDiv,'opacity',100)  
  7.             })  
  8.         })  
  9.     }  
  10. }  
  11. function getStyle(obj,attr){  
  12.     if(obj.currentStyle){  
  13.         return obj.currentStyleattr[attr];  
  14.     }else{  
  15.         return getComputedStyle(obj, false)[attr];  
  16.     }  
  17. }  
  18.                                                                       
  19. function startMove(obj,attr,iTarget,fn){  
  20.     clearInterval(obj.timer);  
  21.     obj.timer = setInterval(function(){  
  22.         var iCur = 0;  
  23.         if(attr == 'opacity'){  
  24.             iCur = parseInt(parseFloat(getStyle(obj, attr))*100);  
  25.         }else{  
  26.             iCur = parseInt(getStyle(obj,attr));  
  27.         }  
  28.         var iSpeed = (iTarget - iCur) / 8;  
  29.         iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);  
  30.         if(iCur == iTarget){  
  31.             clearInterval(obj.timer);  
  32.             //回调函数  
  33.             if(fn) fn();  
  34.         }else{  
  35.             if(attr=='opacity'){  
  36.                 iCur += iSpeed  
  37.                 obj.style.filter='alpha(opacity:' + iCur + ')';  
  38.                 obj.style.opacity=iCur / 100;  
  39.             }  
  40.             else{  
  41.                 obj.style[attr]=iCur+iSpeed+'px';  
  42.             }  
  43.             document.title = obj.style[attr];  
  44.         }  
  45.                                                                         
  46.     },30)  
  47. }  

7.同时运动

目前为止,我们的运动框架还有个小缺点,就是不能同时该两个属性进行运动,比如同时更改宽和高。这个要求传入的属性是不同的几个值。则考虑传入一个 json用来保存需要更改的属性。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var oDiv = document.getElementById('div1');  
  3.     oDiv.onclick = function(){  
  4.         startMove(this,{'width':300,'height':400});  
  5.     }  
  6. }  
  7. function getStyle(obj, attr){  
  8.     if(obj.currentStyle)    {  
  9.         return obj.currentStyle[attr];  
  10.     }else{  
  11.         return getComputedStyle(obj, false)[attr];  
  12.     }  
  13. }  
  14. function startMove(obj,json,fn){  
  15.     clearInterval(obj.timer);  
  16.     obj.timer = setInterval(function(){  
  17.      // 循环json   
  18.      for(var attr in json){        
  19.             var iCur = 0;  
  20.             if(attr == 'opacity'){  
  21.                 iCur = parseInt(parseFloat(getStyle(obj, attr))*100);  
  22.             }else{  
  23.                 iCur = parseInt(getStyle(obj,attr));  
  24.             }  
  25.             var iSpeed = (json[attr] - iCur) / 8;  
  26.             iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);  
  27.             if(iCur == json[attr]){  
  28.                 clearInterval(obj.timer);  
  29.                 if(fn) fn();  
  30.             }else{  
  31.                 if(attr=='opacity'){  
  32.                     iCur += iSpeed  
  33.                     obj.style.filter='alpha(opacity:' + iCur + ')';  
  34.                     obj.style.opacity=iCur / 100;  
  35.                 }  
  36.                 else{  
  37.                     obj.style[attr]=iCur+iSpeed+'px';  
  38.                 }  
  39.                 document.title = obj.style[attr];  
  40.             }  
  41.         }  
  42.     },30)  

上述代码,可以解决了同时运动的问题。但是还是有一个bug。比如,同时运动的某个属性,如果变化很小,马上就停止了,即关掉了定时器。那么会造成其他属性的变化也停止。因为这些属性都共用了一个定时器。因此需要判断,假设有三个人要来,然后一起去爬山。三个人有的先来,有的后来,只要三个人都到齐了,才出发。也就是只有三个属性都到了目标值,才关定时器。一开始,设立一个检查量,为真。假设所有人都到了,然后循环,只有有一个人没有到,检查就为假。直到所有的都到了,检测为真。则停止定时器。

[javascript] view plain copy
  1. window.onload = function(){  
  2.     var oDiv = document.getElementById('div1');  
  3.     oDiv.onclick = function(){  
  4.         startMove(this,{'width':102,'height':400,'opacity':100});  
  5.     }  
  6. }  
  7. function getStyle(obj, attr){  
  8.     if(obj.currentStyle)    {  
  9.         return obj.currentStyle[attr];  
  10.     }else{  
  11.         return getComputedStyle(obj, false)[attr];  
  12.     }  
  13. }  
  14. function startMove(obj,json,fn){  
  15.     clearInterval(obj.timer);  
  16.     obj.timer = setInterval(function(){  
  17.         var bStop = true;  
  18.         for(var attr in json){    
  19.             //取当前值    
  20.             var iCur = 0;  
  21.             if(attr == 'opacity'){  
  22.                 iCur = parseInt(parseFloat(getStyle(obj, attr))*100);  
  23.             }else{  
  24.                 iCur = parseInt(getStyle(obj,attr));  
  25.             }  
  26.             //计算速度  
  27.             var iSpeed = (json[attr] - iCur) / 8;  
  28.             iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);  
  29.             //检测停止  
  30.             if(iCur != json[attr]){  
  31.                 bStop = false;  
  32.             }     
  33.             if(attr=='opacity'){  
  34.                 iCur += iSpeed  
  35.                 obj.style.filter='alpha(opacity:' + iCur + ')';  
  36.                 obj.style.opacity=iCur / 100;  
  37.             }  
  38.             else{  
  39.                 obj.style[attr]=iCur+iSpeed+'px';  
  40.             }  
  41.         }  
  42.         if(bStop){  
  43.             clearInterval(obj.timer);  
  44.             if(fn) fn();  
  45.         }  
  46.     },30)  
  47. }  

再循环外定义一个 标志变量 bStop = true。用来表示所有属性到达目标值。等循环结束了,如果这个值是真的,则停止定时器。因为,每次运行定时器,都会初始化这个值。循环的过程中,只要有一个没有到,bStop就被设定为 false。如果某个到了,此时 iCur != json[attr],表示速度为0 后面执行的结果,也不会有变化。只有所有的都达到目标值。循环则不再改变 bStop的值。此时,只要下一次运行定时器。就是初始化 bStop为真。而循环因为都到了,所以速度为0 也就再也没有变化。循环结束,sBstop还是真,表示所有都到了。因此此时结束定时器。

 

最后附上完美运动框架,封装成 move.js 就可以调用了。

[javascript] view plain copy
  1. /** 
  2.  * @author rsj217 
  3.  * getStyle 获取样式 
  4.  * startMove 运动主程序 
  5.  */  
  6.                  
  7. function getStyle(obj, attr){  
  8.     if(obj.currentStyle)    {  
  9.         return obj.currentStyle[attr];  
  10.     }else{  
  11.         return getComputedStyle(obj, false)[attr];  
  12.     }  
  13. }  
  14. function Move(obj,json,fn){  
  15.     //停止上一次定时器  
  16.     clearInterval(obj.timer);  
  17.     //保存每一个物体运动的定时器  
  18.     obj.timer = setInterval(function(){  
  19.         //判断同时运动标志  
  20.         var bStop = true;  
  21.         for(var attr in json){    
  22.             //取当前值    
  23.             var iCur = 0;  
  24.             if(attr == 'opacity'){  
  25.                 iCur = parseInt(parseFloat(getStyle(obj, attr))*100);  
  26.             }else{  
  27.                 iCur = parseInt(getStyle(obj,attr));  
  28.             }  
  29.             //计算速度  
  30.             var iSpeed = (json[attr] - iCur) / 8;  
  31.             iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);  
  32.             //检测同时到达标志  
  33.             if(iCur != json[attr]){  
  34.                 bStop = false;  
  35.             }     
  36.             //更改属性,获取动画效果  
  37.             if(attr=='opacity'){  
  38.                 iCur += iSpeed  
  39.                 obj.style.filter='alpha(opacity:' + iCur + ')';  
  40.                 obj.style.opacity=iCur / 100;  
  41.             }  
  42.             else{  
  43.                 obj.style[attr]=iCur+iSpeed+'px';  
  44.             }  
  45.         }  
  46.         //检测停止  
  47.         if(bStop){  
  48.             clearInterval(obj.timer);  
  49.             if(fn) fn();  
  50.         }  
  51.     },30)  
  52. }  

 

至此,运动框架封装完毕。使用的时候,引入 move.js即可。


http://blog.csdn.net/rsj217/article/details/7986905


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩挨打不会还手怎么办 孩子挨打不敢还手怎么办 武警森林改革新兵怎么办 森林武警新兵后来怎么办 部队训练打死人怎么办? 部队受伤退伍后怎么办 60岁失地养老怎么办 梦遗到被子上怎么办 血管打针打的硬怎么办 征兵彩超不过怎么办? 警卫局退役新兵怎么办 有轻微的肾结石怎么办 部队改制边防义务兵怎么办 在部队班长打人怎么办 肾结石在上盏怎么办 带新兵废嗓子怎么办 部队干部想复原怎么办 眼睛度数越来越高怎么办 驾照视力不够4.9怎么办 矫正视力达不到1.0怎么办 原材料复检批次不足怎么办 二年级视力4.5怎么办 儿童400度近视怎么办 境外汇款退回该怎么办 小米快件被退回怎么办 快递自动退回该怎么办 信用卡退回去了怎么办 车子排气污染不合格怎么办 被同学举报作弊怎么办 军检体重不合格怎么办 当兵体检不会蹲怎么办 蟑螂的卵鞘被捏暴了怎么办 睾丸被挤变形怎么办 口香糖粘鞋边上怎么办 鞋底上的口香糖怎么办 鞋底踩了口香糖怎么办 被够狗咬了没出血怎么办 阴囊破皮化脓怎么办 阴囊皮挠破了疼怎么办 洗澡洗不干净怎么办 睾丸整个碎了怎么办