您的位置:首页 > Web前端 > JavaScript

javascript动画、运动算法详细解释与分析 (二、javascript动画 时间精度问题)

2011-05-13 19:57 841 查看
三、时间精度问题

首先我们必须知道出现时间精度问题的原因。

如果你对javascript单线程机制不太熟悉,或者对setInterval、setTimeOut函数执行机制不太理解,希望你能先看一下这篇文章:HowJavaScriptTimersWork[Copy]。然后你可以看一下这篇文章http://icolin.org/javascript/settimeout-bug-in-ie-with-winxp.html。第一篇文章可以帮助你理解javascript单线程机制以及setInterval、setTimeOut函数的执行机制,第二篇文章中iColin童鞋已经对时间精度问题出现的情况作了详细的描述,他和我们在这里的问题是一样的,所以我就不再复述。最后一定要看Omiga的再谈JavaScript时钟中的16ms精度问题这篇文章。

(希望你确实看了那三篇文章,这样你才能更加容易的理解下面的内容)

那么现在相信你对问题出现的原因已经理解的差不多了,我在这里再做一下小结:

javascript动画在浏览器中运行的过程中会产生时间误差,误差由系统环境,浏览器环境,程序运算时间,以及其他人为原因造成(我们这里排除人为错误导致的误差)。那么系统环境包括计算机硬件、计算机操作系统,浏览器环境包括浏览器内核、javascript解释引擎等,程序运算时间虽然有时可以忽略,但程序却可能由于javascript的单线程机制造成时间延迟。所以如果想把时间精确到毫秒,那是很有难度的,jQuery也考虑到了这个问题,所以她采用了消息队列机制来尽量的消除这种误差,不过效果差强人意。因为程序本身的时间精度就很难控制,所以如果使用程序本身来控制时间精度,那就好像拿油灭火。。。因为有很多不可抗力因素和外力因素影响。所以我们暂且将动画时间精确到秒。

这里对时间精度问题的讨论就先到这里,如果你有更好的解决方案,非常非常希望你能给予指导,非常非常感谢。

在这里我们顺便顺便解释一下上次遗留的(这里为什么是以6px/30ms的速度等下解释)这个问题。

首先要说一下Tween算法,我是从cloudgamer的http://www.cnblogs.com/cloudgamer/archive/2009/01/06/tween.html这篇文章中看到了Tween算法,进而在robertpenner的《Flash_MX编程与创意实现》中看到的非常细致的讲解。网址:http://www.robertpenner.com/easing/。如果想搞Flash创意和动画的朋友推荐看这本书,我看了一部分,讲得不错,网上对这本书的评论也很好,我这里有PDF中文版的,需要的跟我联系。

在Flash中,动画时长都是以帧为单位来计算的。每帧时长*帧数就是动画总时间。在我们javascript中,我们的帧时长实际上就是setInterval、setTimeOut的第二个参数。而帧数就是

Math.prototype.linearTween=function(t,b,c,d){
returnt*c/d+b;
}


上面linear算法中的d和t(d表示总帧数,t表示已经经过的帧数)。

所以如果你就像最开始那样单纯的认为t是时间,可能你就会陷入像我一样的痛苦的迷茫中,半天不能自拔。我们再来复习一下这段代码。

$=function(id){returntypeofid=="string"?document.getElementById(id):id}
/*des:tween算法。
t:动画已经执行的时间(实际上时执行多少次/帧数)
b:起始位置
c:终止位置
d:从起始位置到终止位置的经过时间(实际上时执行多少次/帧数)*/
tween={
linear:function(t,b,c,d){
returnt*c/d+b;
}
}
move={
moveType:function(mvTp){returnmvTp&&typeof(mvTp)==”string”&&tween[mvTp]?mvTp:"linear"},
startMove:function(mvObj,mvTp,t,b,c,d){
t?t:t=0;b?b:b=0;c?c:c=300;d?d:d=50;
$(mvObj).style.position=="relative"||$(mvObj).style.position=="absolute"
?1:$(mvObj).style.position="relative";
//每隔30毫秒重复执行改变元素位置的函数
mvTimer=setInterval(function(){
//判断动画已经执行的时间(次数/帧数)是否小于总时间,是的话继续执行改变位置的函数,否则的话,清理该interval。
t<=d
?function(){$(mvObj).style.left=parseInt(tween[move.moveType(mvTp)](t,b,c,d))+"px";t++;}()
:clearInterval(mvTimer);
},30)
}
}
move.startMove("moveLinear");

在这里我们动画的帧数是d=50,经过帧数为t,当t<=d时,继续执行动画,每帧的时间间隔是30毫秒,该元素将从距离窗口左边距为0的位置移动到距离窗口左边距为300的位置(这里忽略body的默认margin)。

今天先到这里,下次将会接着分析Tween算法,我将尽最大努力来经历这个有意思的东西。

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
章节导航