如何在不同浏览器上解决requestAnimationFrame中不同的FPS?
Posted
技术标签:
【中文标题】如何在不同浏览器上解决requestAnimationFrame中不同的FPS?【英文标题】:How to solve different FPS in requestAnimationFrame on different browsers? 【发布时间】:2011-12-02 15:54:32 【问题描述】:如何解决requestAnimationFrame
在不同浏览器上的不同FPS?
我正在使用 THREE.js
制作一个使用 requestAnimationFrame
的 3D 游戏,并且在 Google Chrome 15 上运行速度很快。
但是,它在 Firefox 6 上真的很慢,在 IE9 上真的很慢(比 Firefox 慢)。
这确实是一个大问题,我想知道是否有解决方案。
谢谢。
【问题讨论】:
解决这个问题的方法是让你从回调中运行的任何代码运行得更快。怎么做到的,不看代码就说不出来了…… 【参考方案1】:常见的做法是创建一个 deltaTime (dt) 变量,然后将其用作每个动画/更新周期的参数。
代码仅用于可视化问题/解决方案。
// ...
timer: function()
var now = new Date().getTime(); // get current time
this.controls.dt = now - this.controls.time; // calculate time since last call
this.controls.time = now; // update the current application time
this.controls.frame++; // also we have a new frame
return this.controls.dt ;
对于渲染函数的任何调用,然后传递 dt
// we call the update function with every request frame
update: function()
var dt = this.timer();
_.each(this.activeViews, function(item) item.update(dt); ); // this is underscore.js syntax
item.update(dt) 是这样的
//...
var x = this.position.get(x);
x = x + (10*dt); // meaning: x increases 10 units every ms.
this.position.x = x;
【讨论】:
【参考方案2】:据我所知,除了减少代码占用的资源之外,没有办法真正解决这个问题。
Chrome 似乎是最快的浏览器,但通常 FF 也不甘落后,但 IE 仍然很慢。根据渲染方法(canvas、svg 或 webGL),它也非常依赖于您的本地硬件,因为它使用客户端处理大多数事情,而复杂的 webGL 渲染需要强大的 GPU 来实现良好的帧速率。
有多种方法可以实时测量帧速率,并相应地更改您的动画。 这是一个测量帧率的非常简单的示例。
function step(timestamp)
var time2 = new Date;
var fps = 1000 / (time2 - time);
time = time2;
document.getElementById('test').innerhtml = fps;
window.requestAnimationFrame(step);
var time = new Date(), i = 0;
window.requestAnimationFrame(step);
<div id="test"></div>
这只是一个不那么准确的即时测量,您可能需要在一段时间内测量的东西,以便为正在使用的浏览器获得更正确的帧速率。
另请注意timestamp
参数,它在requestAnimationFrame
中是高分辨率时间戳,最小精度为 1 毫秒,也可用于确定动画速度和任何浏览器延迟。
【讨论】:
IE9+ 实际上相当快。根据我的经验,有时比 FF 更快。【参考方案3】:在某些浏览器上 requestAnimationFrame 的工作方式类似于
setTimeout(callback, 1000 / (16 + N)
其中 N 是代码执行所需的时间。这意味着它将您的 FPS 上限设置为 62Hz,但如果您的代码运行缓慢,它的上限会更低。它基本上试图在每个间隙之间留出 16 毫秒的间隙。当然,这并非适用于所有浏览器,并且将来可能会发生变化,但它仍然可以让您了解它是如何工作的。
即使它在每个浏览器中实现相同,也有许多因素会影响代码的性能等。您永远无法确定您的代码将以恒定的频率运行。
【讨论】:
【参考方案4】:Crafty 框架做了一些不同的事情,但可能适用于某些情况——每次抽签的游戏滴答数不是恒定的。相反,它会注意到帧速率何时落后于某个理想目标,并会在执行绘制步骤之前循环通过多个游戏节拍。你可以在github上看到step function。
只要游戏能够顺利运行,它就可以很好地工作。但是如果你尝试更多处理器密集型的东西,它可能会加剧这种情况,因为它会优先考虑游戏逻辑而不是动画。
无论如何,它只有在游戏逻辑和渲染逻辑在某种程度上解耦时才会起作用。 (如果它们完全解耦,您也许可以将它们放在完全独立的循环中。)
【讨论】:
【参考方案5】:正如adeneo 提到的,requestAnimationFrame
回调被发送一个时间戳参数。这是使用该时间戳参数测量requestAnimationFrame
事件之间的增量的解决方案,而不是使用Date()
函数创建单独的变量(无论如何performance.now()
可能是更好的解决方案)。
此解决方案还包括一个启动/停止选项,以说明为什么我在每次启动时使用单独的函数来初始化 previousTimestamp,以及我为什么要设置 reqID 值。
var reqID, previousTimestamp, output;
const raf = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
const caf = window.cancelAnimationFrame || window.mozCancelAnimationFrame;
// This is run first to set the previousTimestamp variable with an initial value, and then call the rafLoop function.
const startStop = () =>
if ($('#start-stop').prop('checked'))
reqID = raf(timestamp =>
previousTimestamp = timestamp;
reqID = raf(rafLoop);
);
else caf(reqID);
;
const rafLoop = timestamp =>
animation(timestamp - previousTimestamp);
previousTimestamp = timestamp;
reqID = raf(rafLoop);
;
// Create animation function based on delta timestamp between animation frames
const animation = millisesonds =>
output.html(millisesonds);
;
$(document).ready(() =>
output = $('#output');
$('#start-stop').change(startStop);
$('#start-stop').prop('checked', true).trigger('change');
);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>requestAnimationFrame</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<label for="start-stop">Start/Stop: </label><input class="switch" type="checkbox" id="start-stop"><br>
<div id="output"></div>
</body>
另请参阅 https://codepen.io/sassano/pen/wvgxxMp 以获取另一个包含此 sn-p 派生的动画的示例。
【讨论】:
以上是关于如何在不同浏览器上解决requestAnimationFrame中不同的FPS?的主要内容,如果未能解决你的问题,请参考以下文章