Javascript - 无法调整帧速率 - 请求动画帧

Javascript - Can't Adjust FrameRate - requestanimationframe

本文关键字:请求 动画 帧速率 调整 Javascript      更新时间:2023-09-26

>我开始循环

function gameLoop(){
   update();
   draw();
   requestAnimFrame(gameLoop);
}
var requestAnimFrame =  window.requestAnimationFrame ||
                    window.webkitRequestAnimationFrame ||
                    window.mozRequestAnimationFrame ||
                    window.oRequestAnimationFrame ||
                    window.msRequestAnimationFrame ||
                    function(callback) {
                        window.setTimeout(callback, 1000 / 1);
                    };
  1. 我无法调整帧速率。 它总是非常快。 为什么我不能将其更改为每秒 1 帧。 我想这样做只是为了测试目的。
  2. 我每次都必须清除画布吗? 它似乎在不清除它的情况下工作得很好。

谢谢。

这是完整代码的小提琴链接:完整代码

谢谢

rAF 被锁定到显示器的同步,通常为 60 Hz,因此我们无法为其本身调整 FPS(当选项卡处于非活动状态或使用电池时,浏览器可能会降低 FPS(。

此外,您尝试更改的是多边形填充的回退; 也就是说:如果浏览器中不支持 rAF,它将改为使用 setTimeout .但是,现在大多数浏览器支持rAF(甚至是无前缀的(,因此永远不会使用setTimeout

您可以做两件事:

  • 直接使用setTimeout替换循环中的 rAF(测试时(

例:

var FPS = 1;
function testLoop() {
    ... ordinary code
    setTimeout(testLoop, 1000/FPS);
}
  • 使用计数器限制 rAF:

例:

var framesToSkip = 60,
    counter = 0;
function loop() {
    if (counter < framesToSkip) {
        counter++;
        requestAnimationFrame(loop);
        return;
    }
    /// do regular stuff
    counter = 0;
    requestAnimationFrame(loop);
}

修改小提琴在这里

很可能有更好的方法来实施限制,但我试图展示基本原则。这仍将以 60 FPS 的全速运行,但您的代码将执行最少的操作,并且只有当计数器达到其计数时,它才会执行主代码。

如果您接下来绘制的内容将覆盖以前绘制的内容,或者您当然想保留它,则无需每次都清除画布。如果需要,您还可以清除一部分以进一步优化。

派对有点晚了,但这里是如何在控制帧/秒的同时获得 RAF 的好处。

注意:requestAnimationFrame 现在比使用我原来的 3 年前原始答案中的代码模式有更好的做事方式......请参阅下面的更新,了解新的和改进的方式。

[更新:请求动画帧现在有更好的限制方式]

新版本的 requestAnimationFrame 现在会自动发送当前时间戳,您可以使用该时间戳来限制代码执行。

以下是每 1000 毫秒执行一次代码的示例代码:

var nextTime=0;
var delay=1000;
function gameLoop(currentTime){
    if(currentTime<nextTime){requestAnimationFrame(gameLoop); return;}
    nextTime=currentTime+delay;
    // do stuff every 1000ms
    requestAnimationFrame(looper);
}

}

你应该看看这篇文章,它给出了这个主题的正确处理。http://creativejs.com/resources/requestanimationframe/

var fps = 15;
function draw() {
    setTimeout(function() {
        requestAnimFrame(draw);
        // Drawing code goes here
    }, 1000 / fps);
}

这是我认为你想要的代码,但在原始文章中它说使用了requestAnimationFrame,但在这里我使用的是requestAnimFrame。我想也许它改变了,你现在应该使用requestAnimFrame。requestAnimationFrame对我不起作用,而requestAnimFrame对我有用。

浏览器和JavaScript的工作方式使得设置固定帧速率变得困难。假设你想每一秒做一些事情,比如更新和绘制。一种方法可能是使用一秒的设置调用window.setTimeout()。但问题是这并不那么可靠,即使您每秒配置一次回调,也无法确定所有回调都会及时完成。例如,高处理器负载可能会使回调比应有的时间晚得多。即使回调准时,您也无法控制何时实际绘制到屏幕上。

更好的处理方法是接受这样一个事实,即您无法获得非常精确的通话时间,相反,每当您接到电话时,您都会计算过去了多少时间并据此采取行动。这意味着您将让系统决定帧速率,您只需根据经过的时间负责更新动画或游戏。

requestAnimationFrame是目前大多数浏览器支持的较新功能,对游戏特别有用。每次浏览器准备绘制时都会调用它,这很好。然后,您将知道您正在进行的更新和绘制将在实际帧绘制到屏幕上之前发生。

下面是一个示例,说明如何更新游戏循环以考虑时差。

var lastTimestamp = +new Date;
function gameLoop(timestamp) {
  var now = +new Date;
  var dt = now - lastTimestamp;
  // dt is the amount of time in ms that has passed since last call.
  // update takes this time difference (in seconds) and can then perform its
  // updates based on time passed.
  update(dt / 1000);
  draw();
  lastTimestamp = now;
  requestAnimationFrame(gameLoop);
}
这就是

requestAnimationFrame的工作方式。如果需要特定的帧速率,请仅使用setTimeout

通常你会采用一个参数,即当前时间。将其与最后一帧的时间进行比较,以了解动画应该移动多远。

非常方便的 js 库,如果你需要在 javascript 中控制 Framratehttps://github.com/aaronGoshine/Javascript-OnEnterFrame-Event-Manager/blob/master/index.html

requestAnimationFrame将以可实现的最大帧速率(最高 60 fps(运行。这是因为它总是会给你下一个动画帧。

您调整的参数仅适用于 polyfill,如果您的浏览器没有实现 requestAnimationFrame,该 polyfill 将处于活动状态。

如果您想尝试在一秒钟内绘画以进行测试,请尝试setInterval