RequestAnimationFrame调用时间根据我的画布大小而变化

RequestAnimationFrame call time changes depending on my canvas size

本文关键字:布大小 变化 我的 调用 时间 RequestAnimationFrame      更新时间:2023-09-26

在我的应用程序中,我有一个画布,CSS大小(CSS,而不是html)会根据窗口大小进行更新。

我有一个主要的游戏循环,看起来像这样:

run = function(){
    console.log(timerDiff(frameTime));
    game.inputManage();
    game.logics();
    game.graphics.animate();
    game.graphics.render();
    frameTime = timerInit();
    requestAnimFrame(run);
}

我的请求AnimFrame函数是Paul Irish的函数:

window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       || 
          window.webkitRequestAnimationFrame || 
          window.mozRequestAnimationFrame    || 
          window.oRequestAnimationFrame      || 
          window.msRequestAnimationFrame     || 
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();

所以基本上问题是,我记录的测量requestAnimFrame调用和有效函数调用之间时间的计时器完全改变了。如果我的浏览器是全屏的,我会得到大约50/60毫秒,如果我有一个小窗口,我可以得到大约10毫秒。

由于requestAnimFrame调用应该在60fps的节奏下(我认为大约是30ms)不断调用函数,我不应该有这种结果,因为在计时器的创建和检查之间基本上没有发生任何事情,除了requestAnimFrame

我也有一些反复出现的微冻结(不到一秒钟),每2/3秒就会发生一次。但是计时器没有检测到时间的任何变化(就像javascript的计时器被阻止一样)

我的计时器功能是这样的,但在这里并不重要

timerInit = function()
{
    return new Date();
}
timerDiff = function(datePrev)
{
    return new Date().getTime() - datePrev.getTime();
}

好吧,标准基本上说requestAnimationFrame将"尽其所能"以"一致"的帧速率运行。这并不能保证每秒60帧;它只是声明它将以最快的速度制作动画。

不幸的是,到目前为止,我的经历和你一样暗淡。我最终回到了setTimeout。它的速度大致相同,图形更新是准确的,不会像requestAnimationFrame那样跳过一个节拍。当然不是60帧/秒,但至少你能知道发生了什么。

我相信性能只会随着浏览器开发人员对新功能的优化而提高,但目前,请考虑回到timeouts

编辑:我想提醒人们,这是一年前的答案,时代已经改变了:)

"所以基本上问题是,我记录的测量requestAnimFrame调用和有效函数调用之间时间的计时器完全改变了…"

当然,这就是为什么你需要测量它,并根据这个时间差值计算你的下一帧。

假设您希望以60帧/秒的速度在1秒内将div的"left"css属性从0px动画化为120px。

  • 使用setTimeout,因为您设置了帧数,所以您知道必须增加"left"属性的多少:120px/60frames=2px/frame

  • 使用requestAnimationFrame,您不知道下一帧何时发生,直到它发生;然后你测量这个帧和上一帧之间的时间差,然后你计算出你必须增加css"left value"的值;如果帧发生在500ms之后,则递增距离=(120px*500ms)/1000ms=60px;理想的做法是,在动画开始时,你不能在每一帧都有一个固定的、预先确定的值来增加,你需要根据时间差动态计算它

因此,即使动画不会达到广告中的60fps,如果跳过帧,每个没有跳过的帧都会绘制出准确的更新情况。

你必须稍微调整一下才能决定动画何时结束。