2015-04-30 14 views
8

Qual è il modo migliore per ottenere la differenza di tempo tra il callback "window.requestAnimationFrame" in javascript?Javascript: come ottenere la differenza di orario tra window.requestAnimationFrame

ho provato:

// 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? 
+1

potenziale duplicato: http://stackoverflow.com/questions/8279729/calculate-fps-in-canvas- using-requestanimationframe –

+0

Abbastanza sicuro che al callback sia passato un singolo parametro, un timestamp (in implementazioni native requestAnimationFrame) se cerchi il supporto per il polyfill, ci sono quelli che emulano il parametro timestamp meglio di quello che hai per il tuo window.FPS polyfill. [Questo] (https://gist.github.com/timhall/4078614) è forse uno dei migliori che abbia mai visto. Relativo a [questo] (http://stackoverflow.com/questions/13241314/up-to-date-polyfill-for-requestanimationframe) QUINTA domanda – OJay

+1

Btw, puoi completamente omettere che IEFE e il suo 'return', assegni semplicemente' window.raf = ... || ... || function (cb) {...}; ' – Bergi

risposta

2

maggior parte dei browser moderni inviano automaticamente un timestamp ad alta precisione come un argomento in ogni ciclo requestAnimation richiamata: http://caniuse.com/#search=performance

Quindi è sufficiente sottrarre l'ultimo timestamp dal timestamp corrente per ottenere il tempo trascorso da quando il ciclo è stato eseguito l'ultima volta.

Ecco esempio di codice e una demo:

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); 
 
}
body{ background-color: ivory; } 
 
#canvas{border:1px solid red;}
<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>

Per la coppia di browser che non supportano Performance, si dovrà utilizzare Date.now() invece di currentTime all'interno del ciclo dal momento che nessun timestamp viene automaticamente inviato da quei browser nel loop.

+0

Cosa sta facendo 'parseInt'? Come porta badge js gold dovresti saperlo! – Bergi

+0

@ Bergi. Chuckle, d'accordo! – markE

4

ha "dt" la migliore precisione?

No. Secondo the docs,

Il metodo callback viene passato un singolo argomento, un DOMHighResTimeStamp, che indica il tempo corrente quando callback coda dal requestAnimationFrame cominciano a sparare

quindi dovresti usarlo per ottenere un'alta precisione.

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); 

(jsfiddle demo)

+0

Vale anche la pena notare che il timestamp del rAF sarà in qualche modo quantizzato a 16.67ms, 16.67x2 ecc. in quanto è sincronizzato con la frequenza di aggiornamento del monitor. – K3N

+0

var last = now || Date.now() è sbagliato penso. "now" è il timestamp da quando animationFrame è stato avviato, mentre Date.now() è Unix timestamp – marirena

+0

@marirena: No, 'now'" * indica l'ora corrente * "in base ai documenti, non l'intervallo di tempo dall'invocazione di rAF. È un timestamp in millisecondi assoluto proprio come "Date".now', ma con maggiore accuratezza (e possibilmente un'origine diversa). Puoi omettere completamente il '|| ... 'parte pure, è solo una soluzione per spessori rAF incompatibili. – Bergi

2

scriverò una chiara conclusione, per tutti coloro che vogliono utilizzare questo modello

// CREATING AN FPS ENGINE 

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

var FPS = { 
    loop: function(canvas_object) { // OPTIONAL canvas_object, I think it increases performance | canvas_object = document.getElementById("canvas_id") 
     var ticks = window.FPS(function(now){ 
      var dt = now - FPS.stamp || 0; 
      FPS.stamp = now; 
      FPS.update(dt, FPS.stamp, ticks); 
      FPS.loop(canvas_object); 
     }, canvas_object); 

    }, 
    update: undefined, 
    stamp: undefined 
}; 

// USING THE FPS ENGINE 

FPS.loop(the_canvas_object); // starts the engine 
FPS.update = function(dt, stamp, ticks) { 
    // The game/video loop, using accurate dt. Stamp is the time since engine started. Ticks is the number of the loop cycles 
    console.log("dt: " + dt + ", Stamp: " + stamp + ", Ticks: " + ticks); // check output 
    // HAPPY GAME CREATING 
    var fps= (1/(dt/1000)).toFixed(1); 
}; 
+1

'(1/(dt/1000))' può essere semplificato a questo: '(1000/dt)'. Non so perché l'hai fatto in questo modo. –

Problemi correlati