rAF 循环可实现一致的 requestAnimationFrame 精度和计时

问题描述 投票:0回答:1

我发现有关 JS 中 requestAnimationFrame 计时的矛盾信息,希望得到一些帮助。在这篇文章(1显示的确切时间:requestAnimationFrame 使用和时间轴)中,rAF 时间戳的时间被讨论为因浏览器而异。 但根据文档,它应该“指示前一帧渲染的结束时间”。

线程“显示的确切时间...”讨论了一个独立的 rAF 循环,该循环填充 rAF 请求列表,以便如果我理解正确的话,文档将被视为“动画”。这就是为什么 rAF 时间戳不应变化,而应始终描述下一次疼痛之前的时间(在用户 Kaiido 建议的同一事件循环中)。如果我错了,请务必纠正我。

我想要得到的是一致的时间戳,在浏览器之间不会变化,最好的情况也是绘制帧的时间。 我真的不介意屏幕上框架/对象的调用和显示之间的某种延迟,但我需要非常高的精度(与外部测量相比,基于 JS 测量的误差变化)。对一些 JS 库 的分析表明,通常可以达到 5 毫秒以下的精度。与这项研究类似,我也会使用低延迟输入设备。

原作者(第 1 篇文章)也对该主题进行了研究,但我想进一步了解 rAF 循环导致的差异。为什么空的 rAF 队列会导致时间戳行为不一致?独立的 rAF 循环是否是一个“hacky”解决方案,可能会在几个月后停止工作?

javascript animation settimeout requestanimationframe web-animations
1个回答
0
投票

根据文档,它应该“指示前一帧渲染的结束时间”。

实际上,根据规范1,这应该是浏览器认为它有渲染机会的时间:

  1. 等待至少一个其活动文档的相关代理事件循环为

    eventLoop
    的可导航可能有渲染机会。

  2. eventLoop
    最后渲染机会时间设置为不安全的共享当前时间

然后,最后渲染机会时间被用作

frameTimestamp
,本身由运行动画帧回调算法使用。

那么,浏览器什么时候认为它有渲染机会呢?对于规格来说,它发生在并行的神奇世界中,也就是说,他们并没有真正说出来。

在现实世界中......这取决于。对于确实使用 VSync 信号的系统,Chrome(可能还有 Firefox)将尝试根据收到的前一个信号来猜测何时发出下一个信号。因此,他们会安排一个任务在此时触发。然而,跟踪这个垂直同步并排队新任务是相当消耗资源的,所以在一段时间不需要渲染任何新的东西之后,渲染管道将被暂停,可以这么说。当需要执行新的渲染时,浏览器会丢失最后一个 VSync 信号,因此无法正确估计下一个渲染何时发生。所以它会尽快运行它。
这就是为什么保持文档“动画”会强制浏览器保持渲染管道处于活动状态并跟踪上一个垂直同步,从而使其能够正确猜测下一个垂直同步。所以,是的,在 Chrome 中以其当前的行为,运行一个空的 rAF 循环将允许每帧之间的正确计时,其精度比 5 毫秒高得多。

请注意,自从我编写链接答案以来,Firefox 的行为确实发生了变化,它们现在的行为更像 Chrome,因为它们也会尽快从非动画文档运行 rAF。所以,这个解决方案也可以工作。

在 Safari 中,我不太清楚他们在做什么。无论实际显示器的刷新率如何,桌面 Safari 仍然被限制在 60Hz。我想他们根本不看垂直同步信号,而是使用通用计时器。至于这个计时器的计时精度,遗憾的是我不能透露太多。 IIRC,一些移动版本确实允许更高的帧速率,但我自己从未尝试过这些。

现在,某些系统可能具有可变刷新率(例如 NVIDIA®G-SYNC® 或 AMD 的 FreeSync™),某些系统可能根本没有显示器,或者没有 VSync 等。在这种情况下,很难说不同的浏览器将如何反应,也没有人能说未来浏览器的架构将如何演变。因此,实际上这种“解决方法”可能无法处理所有边缘情况,而且肯定不会永远处理。它仍然应该处理最常见的问题,我相信这已经持续了很长一段时间了。

1。请注意,自从我写了之前链接的答案以及您链接到的论文已经编写以来,我们确实对规范进行了大量编辑。

© www.soinside.com 2019 - 2024. All rights reserved.