如何在所有系统上的所有浏览器上以相同的速度播放JavaScript动画?

时间:2010-06-28 22:35:19

标签: javascript performance animation cross-browser frame-rate

我有一个函数可以计算在X和Y轴上移动的各种对象的动画中的下一帧[我称之为frameRender()]和一个将结果帧应用于对象的函数[我称之为frameDisplay()]。物体不仅从A点移动到B点,它们不断移动,总是接收新的目标坐标。我使用setInterval() 1000/frameRate间隔,但由于浏览器没有准确的时间安排,因此似乎无法正常工作。

问题是:如何确保动画具有恒定的帧速率,并且将在所有系统上的所有浏览器上以相同的速度运行?我已经尝试了一切,即使只是在不同的浏览器上也无法获得准确的结果(我在Firefox和Chrome上测试,Chrome通常显示得更快)。

结果应该是:当它播放缓慢时,动画间隔应首先减小,然后尝试跳过一些帧[跳过frameDisplay()]如果DOM显示缓慢,直到它正确播放。当它快速播放时,动画间隔应该增加,使动画以正确的速度播放。

但是如何保持所有这一切的一致性,因为你不能总是确定浏览器什么时候变慢,或者什么时候它们会快速执行。例如,如果有大幅度的移动,我们减少间隔以保持帧速率稳定,然后突然大多数移动物体停止或不移动太多,它会突然执行得非常快!

有什么想法吗?

3 个答案:

答案 0 :(得分:7)

  

问题是:如何确保动画具有恒定的帧速率,并且在所有系统上的所有浏览器上以相同的速度运行?

你无法对帧率做任何事情。您可以控制的唯一事情是您的应用程序如何根据时间的推移进行更新。这在浏览器之外也是如此,也是游戏开发中的常见主题。

最好的办法是跟踪更新之间的增量(读取:时差)。

(function () {
    function getTime() {
        return new Date().getTime();
    }
    var last = getTime();

    function update(delta) {
        // Update your application state on delta (ms of time passed)
    }

    (function loop() {
        update(last = getTime()-last);
        render();
        setTimeout(loop, 20); // 20 = attempt 50fps
    }());
}());

注意这里使用setTimeout。这是为了避免loop()被调用不同步。即使之前的调用没有完成,setInterval也会继续触发它。

答案 1 :(得分:3)

答案is here,一个由Glenn Fiedler撰写的精彩文章,需要稍微调整才能在Javascript中进行转换,但原则是相同的。基本上,您需要使用累加器来累加增量时序,并基于此执行步骤。无需更改任何物理数学或任何东西,解决方案即插即用。还有一个很酷的插补器可以消除口吃,还可以让你做超级平滑的动作(重放等)。这太棒了,适用于物理学,应该适用于任何基于步的运动。基本上你需要准确的计时游戏动作。

答案 2 :(得分:2)

您可以将动画与系统时间同步。

将当前系统时间保存在变量中。 在所有帧上,然后您想重绘图片检查当前时间 - 您的变量等于某个增量时间。然后重新制作动画。否则等待这种差异