使用 CreateJS 按下鼠标并移动 chrome canvas 至 30FPS

Mouse down and moving drops chrome canvas to 30FPS using CreateJS

我一直在为几个 canvas 游戏项目使用 createjs Easeljs 库。总而言之,我印象深刻,但我最近在 chrome 中遇到了一个阻碍我前进的问题。

当按下鼠标左键并移动鼠标时,FPS 在 chrome 上降至 30(如开发人员工具所报告)。这与游戏通常运行的 60FPS 相比是非常明显的。

为了理解这一点,我删除了一个裸露的 canvas 和自动收报机,但问题仍然存在。所以我迷路了。我可以使用以下代码重现该问题:

<html>
<head>
    <script src="./javascript/easeljs-0.8.1.combined.js"></script>
    <script>
        function init() {
            canvas = document.getElementById("gameCanvas");
            createjs.Ticker.setFPS(60);
            createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNC;

            stage = new createjs.Stage(canvas);
            createjs.Ticker.on("tick", tick);
        };

        function tick(evt)
        {
            stage.update();
        }
    </script>
</head>
<body onLoad="init();" bgcolor="#ffffff">
    <canvas id="gameCanvas" width="1136px" height="640px" style="border: thin black solid; margin: 0 auto;"></canvas>
</body>
</html>

我知道这个问题:Html Canvas lag when Left Mouse is down and moving on Chrome但我看不出它在这种情况下有什么帮助。

有没有人有任何想法或资源来帮助解决这个问题?

编辑:

抱歉,我找到了一种解决方法,将代码设置为

createjs.Ticker.timingMode = createjs.Ticker.RAF;

这解决了这些问题和我遇到的间歇性丢帧问题(但没有提到)

无论如何,任何人都可以解释为什么会发生这种情况,以及如果会导致这种情况,我到底为什么要使用同步代码?

RAF 提供了一个不确定的帧率(即,你不能保证任何特定的帧率),这意味着浏览器可以随意限制或增加 fps 以响应任何数量的事情。似乎 Chrome 可能会在鼠标按下时触发额外的 RAF 事件,以便更频繁地重绘并提供更流畅的鼠标交互。

RAF_SYNC 通过尝试将指定帧率与任意帧率对齐来工作。它有一些容差允许它在帧率不一致时工作,但当指定的帧率明显低于现实世界的 RAF 帧率(例如目标 20 或 30 fps)时,它工作得更好。

来自文档:

Variance is usually lowest for framerates that are a divisor of the RAF frequency. This is usually 60, so framerates of 10, 12, 15, 20, and 30 work well.

在这种情况下,因为您的目标 fps 相当高(基本上可能达到最大 RAF),所以它没有太多回旋余地。当 Chrome 超过 60fps 时,RAF_SYNC 开始无法将帧与它试图达到的帧率对齐。前一帧和当前帧之间没有经过足够的时间,因此它会等待一个额外的帧。结果是帧速率下降到略高于指定速率的一半。在 20 或 30 fps 下,您可能根本不会注意到这一点,因为它可以很好地对齐。

例如,假设 Chrome 跳到 80fps,而您在 RAF_SYNC 模式下的目标是 60fps:

  1. Chrome 触发英国皇家空军事件。
  2. Ticker 查看自上次报价以来经过的时间,发现它只有 12 毫秒,认为它还不够接近其 16.67 毫秒的目标,并等待下一个 RAF 事件
  3. Chrome 触发另一个 RAF 事件。
  4. Ticker 查看并看到自上次滴答以来已经过去了超过 16.67 毫秒,并立即触发滴答,但此时已经过去了 25 毫秒。
  5. 重复。您现在 运行 为 ~40fps 而不是 60fps,即使实际帧速率为 ~80fps。

我希望这是有道理的。