Javascript - 无法调整 FrameRate - requestanimationframe
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19000109/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript - Can't Adjust FrameRate - requestanimationframe
提问by Lumo5
I start the loop
我开始循环
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);
};
- I can't adjust the frame rate. It is always really fast. Why can't I change it to 1 frame a second. I want to do this just for testing purposes.
- Do I have to clear the canvas each time? It seems to work good without clearing it.
- 我无法调整帧率。它总是非常快。为什么我不能将其更改为每秒 1 帧。我想这样做只是为了测试目的。
- 我每次都必须清除画布吗?不清除它似乎工作得很好。
Thanks.
谢谢。
Here is a link to a fiddle for the complete code: complete code
这是完整代码的小提琴链接: 完整代码
Thanks
谢谢
采纳答案by Lumo5
rAF is locked to monitor's sync, typically 60 Hz, so we can't adjust the FPS for it in itself (browser may reduce FPS when tab is inactive or on batteries).
RAF被锁定到监控的同步,通常为60 Hz,因此我们无法自行调整FPS(浏览器可能会在电池上为非活动或电池时减少FP)。
Also, what you are trying to change is the fallback for the poly-fill; that is: if rAF is not supported in the browser it will instead use setTimeout
. However, most browsers nowadays dosupport rAF (even un-prefixed) so the setTimeout
will never be used.
此外,您要更改的是 poly-fill 的回退;也就是说:如果浏览器不支持 rAF,它将改为使用setTimeout
. 但是,现在大多数浏览器都支持 rAF(甚至不带前缀),因此setTimeout
永远不会使用rAF 。
You can do two things:
你可以做两件事:
- Replace rAF in your loop by using
setTimeout
directly (when testing)
setTimeout
直接使用(测试时)替换循环中的 rAF
Example:
例子:
var FPS = 1;
function testLoop() {
... ordinary code
setTimeout(testLoop, 1000/FPS);
}
- Throttle rAF by using a counter:
- 使用计数器限制 rAF:
Example:
例子:
var framesToSkip = 60,
counter = 0;
function loop() {
if (counter < framesToSkip) {
counter++;
requestAnimationFrame(loop);
return;
}
/// do regular stuff
counter = 0;
requestAnimationFrame(loop);
}
There are most likely better ways to implement throttling, but I am trying to just show the basic principle. This will still run at full speed, 60 FPS, but your code will do minimal of operations and only when the counter has reached its count will it execute the main code.
很可能有更好的方法来实现节流,但我只是想展示基本原理。这仍然会以 60 FPS 的全速运行,但您的代码将执行最少的操作,并且只有当计数器达到其计数时才会执行主代码。
You do not need to clear the canvas each time if what you draw next will cover previously drawn content, or if you want to keep it of course. You can also clear a portion to optimize further, if needed.
如果您接下来绘制的内容将覆盖以前绘制的内容,或者您当然想保留它,则无需每次都清除画布。如果需要,您还可以清除一部分以进一步优化。
回答by markE
A bit late to the party, but here's how to get the benefit of RAF while also controlling frames/second.
聚会有点晚了,但这里是如何在控制帧/秒的同时获得 RAF 的好处。
Note: requestAnimationFrame now has a better way of doing things than by using the code pattern in my original 3 year old original answer ... see my update below for the new and improved way.
注意: requestAnimationFrame 现在有比使用我原来 3 岁的原始答案中的代码模式更好的做事方式......请参阅下面的更新以了解新的和改进的方式。
[Update: requestAnimationFrame now has a better way of throttling]
[更新:requestAnimationFrame 现在有更好的节流方式]
The new version of requestAnimationFrame
now automatically sends in a current timestamp that you can use to throttle your code execution.
新版本的requestAnimationFrame
now 会自动发送当前时间戳,您可以使用它来限制代码执行。
Here is example code to execute your code every 1000ms:
以下是每 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);
}
}
}
回答by Steven2163712
You should look at this article which gives a proper treatment of the subject. http://creativejs.com/resources/requestanimationframe/
你应该看看这篇文章,它对这个主题进行了适当的处理。 http://creativejs.com/resources/requestanimationframe/
var fps = 15;
function draw() {
setTimeout(function() {
requestAnimFrame(draw);
// Drawing code goes here
}, 1000 / fps);
}
Here is the code I think you want, but in the original article it said used requestAnimationFrame, but here I am using requestAnimFrame. I think maybe it changed and you're supposed to use requestAnimFrame now. requestAnimationFrame did not work for me while requestAnimFrame did.
这是我认为您想要的代码,但在原始文章中它说使用 requestAnimationFrame,但在这里我使用 requestAnimFrame。我想也许它改变了,你现在应该使用 requestAnimFrame 。requestAnimationFrame 对我不起作用,而 requestAnimFrame 起作用。
回答by Michael Brennan
The way browsers and javascript work makes it difficult to set up a fixed frame rate. Say you want to do something every one second, like updating and drawing. One way of doing that could be to call window.setTimeout()
with a setting of one second. But the problem is that this is not that reliable, even if you configure a callback every second you can't be sure all callbacks will be in time. A high processor load, for example, could make the callbacks arrive much later than they should. And even if the callbacks would be on time, you have no control of when the actual drawing to the screen will happen.
浏览器和 javascript 的工作方式使得设置固定帧速率变得困难。假设你想每一秒都做一些事情,比如更新和绘图。这样做的一种方法可能是window.setTimeout()
设置为一秒进行调用。但问题是这不是那么可靠,即使你每秒配置一个回调,你也不能确定所有的回调都会及时。例如,高处理器负载可能会使回调比应有的时间晚得多。即使回调会准时进行,您也无法控制实际绘制到屏幕的时间。
A better way of handling it is to accept the fact that you can't get a very precise timing of your calls, and instead, whenever you get a call, you calculate how much time has passed and act according to that. This means you'll let the system decide the frame rate, and you just take care of updating your animation or game depending on how much time that has passed.
处理它的更好方法是接受这样一个事实,即您无法获得非常精确的通话时间,相反,无论何时接到电话,您都会计算已经过去了多少时间并据此采取行动。这意味着您将让系统决定帧速率,您只需根据已经过去的时间来更新动画或游戏。
requestAnimationFrameis a newer functionality supported by most browsers by now that is especially useful for games. It will be called every time the browser is ready to draw, which is good. Then you will know that the updates and drawing you are doing will happen right before the actual frame is drawn to screen.
requestAnimationFrame是目前大多数浏览器都支持的新功能,对游戏特别有用。每次浏览器准备绘制时都会调用它,这很好。然后你就会知道你正在做的更新和绘图将在实际帧被绘制到屏幕之前发生。
Here's an example on how you could update your gameLoop to take the time difference into account.
下面是一个关于如何更新 gameLoop 以将时差考虑在内的示例。
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);
}
回答by Aaron Goshine
Quite handy js library if you need to control Framrate in javascript https://github.com/aaronGoshine/Javascript-OnEnterFrame-Event-Manager/blob/master/index.html
如果您需要在 javascript https://github.com/aaronGoshine/Javascript-OnEnterFrame-Event-Manager/blob/master/index.html 中控制帧率,这是一个非常方便的 js 库
回答by David
requestAnimationFrame
will run with the maximum achievable frame rate (up to 60 fps). This is because it will always give you the next animation frame.
requestAnimationFrame
将以可达到的最大帧速率(最高 60 fps)运行。这是因为它总是会给你下一个动画帧。
The parameter you adjusted is only for the polyfill, which will be active if your browser has no implementation of requestAnimationFrame
.
您调整的参数仅适用于 polyfill,如果您的浏览器没有实现requestAnimationFrame
.
If you want to try painting at one second for testing purposes, try setInterval
instead.
如果您想尝试在一秒钟内绘制以进行测试,请尝试setInterval
。
回答by Niet the Dark Absol
That's how requestAnimationFrame
works. If you want a specific framerate, use setTimeout
only.
这就是requestAnimationFrame
工作原理。如果您想要特定的帧率,请setTimeout
仅使用。
Usually you would take a parameter, which is the current time. Compare it to the last frame's time to find out how far along the animation should move.
通常你会带一个参数,即当前时间。将其与最后一帧的时间进行比较,以确定动画应移动多远。