【问题标题】:reduce / thottle requestAnimationFrame for Canvas animation减少/限制画布动画的 requestAnimationFrame
【发布时间】:2016-06-11 17:12:45
【问题描述】:

我正在创建 HTML5 Canvas 动画并希望降低/限制帧速率。我目前正在使用 requestAnimationFrame 方法。为了限制帧速率,我使用了 setTimeout。

有没有更好/更有效的方法来做到这一点?

// Game - animation loop 
      var fps = 5;
      function step() {
        setTimeout(function() {
          update();
          draw();
          window.requestAnimationFrame(step);
        }, 1000 / fps);
      }

谢谢

【问题讨论】:

  • 我觉得这个答案可以给你解释stackoverflow.com/a/19772220/2542172
  • requestAnimationFrame 现在会自动发送时间戳,您可以使用该时间戳来限制代码的执行。请参阅此Q&A。 :-)

标签: javascript html html5-canvas requestanimationframe


【解决方案1】:
const fps = 5;
const delay = Math.ceil(1000 / fps);
let last = Date.now();
let now;

function step () {
    now = Date.now();
    if(now - last < delay) {
        return requestAnimationFrame(step);
    }
    last = now;
    update();
    draw();
    requestAnimationFrame(step);
}

step();

【讨论】:

  • 感谢 azamantes 和 Rudolf .. @ azamantes,我认为如果我用 'var' 替换 const 和 let 这将起作用?
  • 当然,constlet 是 ES6 语法,你可以很好地用旧的 var 替换它们。在这种特殊情况下,我认为他们的行为不会与预期不同。
  • 我会指出,传递给requestAnimationFrame 的回调是使用一个参数调用的,该参数包含一个高精度时间戳,自页面加载以来的时间以毫秒为单位。所以不需要Date.now() 电话。应该有function step( time ) 这将使时间达到 1/1,000,000 秒的精度,并避免您可以使用 1/1000 日期计时器获得的跳帧。
  • 是的,您会得到InternalError: too much recursion ,因为递归调用相同的函数并以您的 1/10000000...秒精度阻塞整个页面。 requestAnimationFrame 让浏览器有时间在每秒 5 帧之间做其他事情 :) 你永远不应该无限递归地调用你的函数,因为计算机太快了,你只会得到一个错误。而对于我们人类来说,那些 16 毫秒的差异延迟(在最坏的情况下)真的不会产生任何影响。这是最坏的情况。
  • Azamantes 您对@Blindman67 的评论不正确。 requestAnimationFrame 自动将其执行限制为显示刷新速度(通常为每秒 60 次),因此您永远不会有“失控”的 rAF。并且 rAF 是伪异步的,因为它允许 rAF 回调之间的所有非 rAF 活动。此外,IME、现代浏览器优化了 rAF 循环,因此任何不执行任何操作的特定 rAF 回调(因为它们正在等待您想要的延迟时间)对性能的影响非常小。
猜你喜欢
  • 2019-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-08
  • 1970-01-01
  • 2015-03-14
  • 2021-02-24
相关资源
最近更新 更多