requestAnimationFrame不流利

时间:2016-11-28 05:38:00

标签: javascript webgl requestanimationframe

我正在编写一些WebGL动画,但我无法使requestAnimationFrame工作得很流畅。我写了这个空循环来在不同的浏览器中测试它:

<html>
    <body>
        <script type="text/javascript">

            var prev = Date.now();

            function frame()
            {
                window.requestAnimationFrame(frame);

                var now = Date.now();
                var diff = now - prev;
                prev = now;

                if(diff > 20)
                {
                    console.log(new Date().toLocaleTimeString() + ": " + diff);
                }
            }

            frame();

        </script>
    </body>
</html>

如果超过20毫秒,它会计算帧和日志之间传递给控制台的时间。我的设置是:Windows 7 x64,Intel i7,Sapphire Tri-X R9 290,16 GB RAM。显示频率为60 Hz,因此我希望帧间的间隙为1/60 = 16.666(6)ms。所以我设置了20毫秒的阈值以防止控制台泛滥。一切都在背景中发生,一切都是空闲的。没有其他浏览器标签打开。这是我的数字:

Google Chrome:

7:47:13 AM: 53
7:47:16 AM: 53
7:47:19 AM: 53
7:47:22 AM: 53
7:47:25 AM: 54
7:47:28 AM: 53
7:47:31 AM: 53
7:47:34 AM: 53
7:47:37 AM: 54
7:47:40 AM: 54
7:47:43 AM: 54
7:47:46 AM: 54
7:47:49 AM: 55
7:47:52 AM: 54
7:47:55 AM: 54

你可以清楚地看到模式:每3秒53-55毫秒的差距。好的,试试另一个浏览器:

FireFox:

7:49:25: 53
7:49:25: 89
7:49:26: 88
7:49:28: 51
7:49:28: 42
7:49:28: 105
7:49:28: 52
7:49:28: 21
7:49:28: 29
7:49:34: 23
7:49:34: 22
7:49:38: 27
7:49:39: 55
7:49:39: 51
7:49:39: 108
7:49:45: 35
7:49:45: 43
7:49:45: 24
7:49:45: 103
7:50:09: 45
7:50:18: 22
7:50:19: 31
7:50:25: 59
7:50:25: 33
7:50:25: 21

更糟糕!好的,让我们继续吧。 Opera与Chrome一样具有相同的引擎,但令人惊讶的是它显示了几乎完美的时序,因此我将阈值降低到大于17毫秒:

Opera:

7:56:57 AM: 18
7:57:00 AM: 18
7:57:12 AM: 18
7:57:13 AM: 18
7:57:17 AM: 18
7:57:19 AM: 18
7:57:32 AM: 18
7:57:33 AM: 18
7:57:34 AM: 18
7:57:37 AM: 18
7:57:48 AM: 18
7:57:50 AM: 18
7:57:51 AM: 18
7:57:54 AM: 18
7:57:55 AM: 18

有趣的部分是它的功能几乎完美,直到你不触摸键盘和鼠标。如果移动鼠标光标,则可以写入此18 ms消息。而最大的惊喜 - IE11。在页面刷新后几秒钟消息后,它可以在不到1毫秒的精度下完全流畅地工作几分钟。干得好,IE11。

IE11:

7:59:25:18

7:59:25:18

那么,发生了什么?为什么这些行为如此不同?如何在所有浏览器中制作流畅的WebGL动画?

更新 我已将日志记录条件更改为:if(diff> 17 || diff&lt; 16)并且我发现Google Chrome和FireFox有时只有几毫秒的间隙,例如1-2-3毫秒。所以看起来他们正试图保持动画VSynced,但他们并没有做得很好。所以我的问题仍然存在。

1 个答案:

答案 0 :(得分:1)

我在Chrome或Firefox中的MBP上看起来并不像你那么糟糕。事实上,我看到前1-3帧之后没有问题。

以下是您的示例内联。我改变了一点,使用传递给requestAnimationFrame而不是Date.now的时间,因为传递给requestAnimationFrame的时间更准确。

我会注意到我已经打开了23个标签页,其中很多标签包括Stack Overflow本身在后台执行的操作,例如发送通知的websockets等。

PS:我认为你的意思是&#34;流畅的&#34;而不是&#34;流利&#34;?

&#13;
&#13;
var prev = 0;
var frameCount = 0;

function frame(now)
{
  ++frameCount;
  var diff = now - prev;
  prev = now;

  if(diff > 20)
  {
    console.log(frameCount, new Date().toLocaleTimeString(), ": ", diff);
  }

  // It's easier to debug things with this at the bottom
  requestAnimationFrame(frame);
}

requestAnimationFrame(frame);
&#13;
&#13;
&#13;