如何确定在 JavaScript 动画循环中使用的最佳“帧速率”(setInterval 延迟)?

IT技术 javascript jquery
2021-03-07 17:06:06

在编写 JavaScript 动画时,您当然会使用 setInterval(或重复的 setTimeout)进行循环。但是在 setInterval/setTimeout 调用中使用的最佳延迟是多少?

.animate() 函数jQuery API 页面中,用户“fbogner”说:

如果有人感兴趣:动画使用 setInterval 进行“渲染”,时间超过 13 毫秒。这是相当快的!Chrome 可能的最快间隔约为 10 毫秒。所有其他浏览器在大约 20-30 毫秒内“采样”。

知道 jQuery 是如何决定使用这个特定数字的吗?


开始赏金。我希望了解 Chromium 或 Firefox 背后源代码的人可以提供一些确凿的事实,这些事实可能会支持特定帧率的决定。或者可能是一系列动画(或框架)及其延迟。我相信这是进行一些研究的有趣机会。


有趣 - 我只是花时间查看 Google 的Pac-Man源代码,看看他们做了什么。他们设置了一系列可能的 FPS(90、45、30),从第一个开始,然后每帧检查帧的“慢度”(帧超过其分配时间的数量)。如果慢度超过 50 毫秒 20 次,帧率将下降到列表中的下一个 (90 -> 45, 45 -> 30)。似乎帧率永远不会提高,大概是因为游戏的生命周期如此短暂,以至于不值得为之编写代码。

哦,setInterval 延迟当然设置为 1000 / 帧率。事实上,他们确实使用了 setInterval 而不是重复的 setTimeouts。

我认为这个动态帧率功能非常简洁!

5个回答

我敢说,很大一部分网络用户正在使用以 60Hz 刷新的显示器,这意味着每 16.66 毫秒刷新一帧。因此,要使监视器成为瓶颈,您需要生成比 16.66 毫秒更快的帧。

您选择 13ms 这样的值有两个原因。首先,浏览器需要一点时间来重新绘制屏幕(根据我的经验,绝不会少于 1 毫秒)。这让您每 15 毫秒更新一次,这恰好是一个非常有趣的数字 - Windows 上的标准计时器分辨率是 15 毫秒(请参阅John Resig 的博客文章)。我怀疑编写良好的 15 毫秒动画在各种浏览器/操作系统上看起来非常相似。

FWIW,fbogner关于非 Chrome 浏览器每 20-30 毫秒触发一次 setInterval是完全错误的我写了一个测试来测量 setInterval 触发的速度,并得到这些数字:

  • 铬 - 4ms
  • 火狐 3.5 - 15 毫秒
  • IE6 - 15 毫秒
  • IE8 - 15 毫秒
截至今天,我在所有主要浏览器(Chrome 40、Firefox 34、Safari 7、IE 8/9/10)中的运行时间约为 4 毫秒。
2021-04-19 17:06:06
John Resig 的博客文章或许应该指向ejohn.org/blog/accuracy-of-javascript-time
2021-05-07 17:06:06
4.024ms在 FF 8 上,4.852ms在 Chrome 16 上。感谢您的测试。
2021-05-16 17:06:06

这个的伪代码是这样的:

FPS_WANTED = 25 
(just a number, it can be changed while executing, or it can be constant)

TIME_OF_DRAWING = 1000/FPS_WANTED 
(this is in milliseconds, I believe it is accurate enough) 
( should be updated when FPS_WANTED changes)

UntilTheUserLeavesTheDrawingApplication()
{

  time1 = getTime();
  doAnimation();
  time2 = getTime();
  animationTime = time2-time1;

  if (animationTime > TIME_OF_DRAWING)
  {
     [the FPS_WANTED cannot be reached]
     You can:
     1. Decrease the number of FPS to see if a lower framerate can be achieved
     2. Do nothing because you want to get all you can from the CPU
  }
  else
  {
     [the FPS can be reached - you can decide to]
     1. wait(TIME_OF_DRAWING-animationTime) - to keep a constant framerate of FPS_WANTED
     2. increase framerate if you want
     3. Do nothing because you want to get all you can from the CPU
  }

}

当然,这可能会有变化,但这是在任何动画情况下都有效的基本算法。

为动画执行循环时,最好在循环速度和需要完成的工作量之间找到平衡。

例如,如果您想在一秒钟内在页面上滑动一个 div,那么这是一个很好的效果和及时的。您将跳过坐标并具有相当快的循环时间,因此效果很明显,但不会跳动。

所以这是一个反复试验的事情(必须将工作、时间和浏览器功能考虑在内)。所以它不仅在一个浏览器上看起来不错。

fbogner告诉的数字已经过测试。浏览器会在一定程度上限制 js-activity 以便每次都可用。

如果您的 javascript 可以每 5 毫秒运行一次,那么浏览器运行时刷新渲染或对用户输入(点击)做出react的 CPU 时间就会少得多,因为 javascript 执行会阻止浏览器。

我认为 chrome-devs 允许您以比其他浏览器更短的间隔运行您的 javascript,因为它们的 V8-Javascript-Engine 编译 JavaScript,因此它运行得更快,只要使用解释的 js 代码,浏览器就不会被阻止.

但是引擎不仅速度更快,允许更短的时间间隔,开发人员肯定已经测试过,这是最好的最短时间间隔,允许短时间间隔并且不会长时间阻塞浏览器

您在问题中引用的人 xD
2021-04-21 17:06:06
哦,哈哈!我什至不记得了,因为我几周前写了这个问题......
2021-04-21 17:06:06

不知道 jQuery 间隔时间背后的原因,因为 13ms 转换为 80fps,这是非常快的。电影中使用的“标准”fps 为 25fps,并且速度足够快,人眼不会注意到任何抖动。25fps 转换为 40 毫秒,因此回答您的问题:低于 40 毫秒的任何内容都足以制作动画。

电影以 24 fps 的速度拍摄,这足以捕捉自然的运动模糊。看电影时,你的大脑会让一切变得平滑。动态渲染的动画不会有从现实生活中捕捉到的好处。
2021-05-04 17:06:06
对于游戏,抖动在 30 fps 时很明显。当您以 200 fps 播放时,它下降到 40 fps,这很明显。再说一次,这可能与显示器刷新有关......顺便说一句,浏览器渲染时是否使用垂直同步?如果是这样,你几乎被锁定在 50/60 fps...
2021-05-13 17:06:06