2013-03-05 22 views
0

我一直在玩HTML5和Canvas,所以我会很高兴为我正在做的事情提供一个恒定的帧率。为此,我试图使用JavaScript的setInterval,但似乎setInterval比期望的循环更快。SetInterval发生得比预期的要快

出于测试目的,我编造了一个小的测试脚本,内容如下:

var start = new Date(); 
var frames = 0; 

setInterval(function() { 
    frames++; 
    var d = new Date(); 
    if (d.getTime() - start.getTime() > 1000) { 
     console.log(frames); 
     frames = 0; 
     start = d; 
    } 
}, 1000/60); 

此脚本理应打印许多“帧”如何在一秒钟内进行计数。如果setInterval正常工作,它会在控制台上不断打印“60”。但是,Chrome和Firefox给我每秒63帧,而Internet Explorer 9给我每秒66到67帧(总是最差的违规者)。

将1000毫秒提高到20000,在Chrome上我平均为62.5 fps,在Firefox上为62.4 fps,在Internet Explorer上为66.0。

我读过这个very enlightening article on Mozilla关于setTimeout他们提到“夹紧”,我认为这可能是一个可能的原因。但是,对于60fps,超时将是16.6ms,比所使用的任何夹具都高。

我也认为这可能是一个计时器错误,给我一个或两个框架关闭,但与20000毫秒测试返回相同的平均帧数,所以它不是定时器。

关于我在做什么错的任何想法?这是一个非常奇怪的行为。对于任何反馈,我们都表示感谢。

回答

1

为setTimeout的延迟是一个整数(毫秒)。 1000/6016.67,它被截断为161000/1662.5。 IE的时钟以15ms的增量运行,因此它可能以15ms的间隔运行该功能,因此66.7 fps。

所有符合你观察到的行为。

最重要的是,你有setTimeout和setInterval的变化无法准确地运行在所请求的延迟,所以如果系统突然变得忙碌(例如响应网络请求,滚动操作等)帧速率将会变慢或变得生涩,试图赶上。

0

不幸的是,这种方法不会产生一致的结果。您必须考虑有问题的脚本的实际执行时间,尽可能短。

我听说requestAnimationFrame在这个用途上效果更好。

A snippet from the Mozilla Developer Network about it.

A nice article about it

+0

如果[John Resig](http://ejohn.org/blog/how-javascript-timers-work/)是正确的(他似乎至少在这一点上),setInterval不会等待(如果它那么,OP的结果会不同)。它将以指定的时间间隔安排新的呼叫,即使最后一个仍在执行。如果有人在等待被叫,它不会排队。 – RobG 2013-03-05 08:32:24

+0

非常感谢,这个功能看起来很有趣。我认为我的应用程序足够轻量,以确保它不会达到文章中描述的计时器上限。 – 2013-03-05 11:40:49