Javascript:如何获得window.requestAnimationFrame之间的时差

mar*_*ena 9 javascript time frame-rate canvas requestanimationframe

在javascript中获取"window.requestAnimationFrame"回调之间时差的最佳方法是什么?

我试过了:

// create the best .requestAnimationFrame callback for each browser
window.FPS = (function() {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
    function(callback) {window.setTimeout(callback, 1000 / 60);};
})();

// start animation loop
var dt, stamp = (new Date()).getTime();
function loop() {
    window.FPS(loop);
    var now = (new Date()).getTime();
    var dt = now - stamp;
    stamp = now;
}
// has "dt" the best accuracy?
Run Code Online (Sandbox Code Playgroud)

mar*_*rkE 7

大多数现代浏览器会自动将高精度时间戳作为参数发送到每个 requestAnimation 回调循环中:http : //caniuse.com/#search=performance

因此,您只需从当前时间戳中减去最后一个时间戳即可获得自上次运行循环以来经过的时间。

这是示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var startingTime;
var lastTime;
var totalElapsedTime;
var elapsedSinceLastLoop;

var $total=$('#total');
var $loop=$('#loop');

requestAnimationFrame(loop);

function loop(currentTime){
  if(!startingTime){startingTime=currentTime;}
  if(!lastTime){lastTime=currentTime;}
  totalElapsedTime=(currentTime-startingTime);
  elapsedSinceLastLoop=(currentTime-lastTime);
  lastTime=currentTime;
  $total.text('Since start: '+totalElapsedTime+' ms');
  $loop.text('Since last loop: '+elapsedSinceLastLoop+' ms');
  requestAnimationFrame(loop);
}
Run Code Online (Sandbox Code Playgroud)
body{ background-color: ivory; }
#canvas{border:1px solid red;}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<p id=total>T1</p>
<p id=loop>T2</p>
<canvas id="canvas" width=300 height=300></canvas>
Run Code Online (Sandbox Code Playgroud)

对于不支持 的几个浏览器Performance,您将不得不使用Date.now()而不是currentTime在循环内使用,因为这些浏览器不会自动将时间戳发送到循环中。


Ber*_*rgi 5

“dt”的准确度最高吗?

不,根据文档

回调方法传递一个参数,即DOMHighResTimeStamprequestAnimationFrame ,它指示开始触发排队的回调的当前时间

所以你应该使用它来获得高精度。

function loop(now) {
    var last = now || Date.now(); // fallback if no precise time is given
    window.FPS(function(now) {
        now = now || Date.now();
        var dt = now - last;
        if (dt != 0) // something might be wrong with our frames
             console.log(dt);
        loop(now);
    });
}
window.FPS(loop);
Run Code Online (Sandbox Code Playgroud)

jsfiddle 演示