54 votes

JavaScript fournit-il une minuterie haute résolution?

N'JavaScript fournir une haute résolution de la minuterie?

J'ai écrit quelques moteurs de jeu à partir de zéro, certains en C, certains en Java, et certains en Flash. J'ai toujours suivre le même modèle de base quand il s'agit de animations et des graphiques interactifs. Créer une classe de base/la structure avec le dessin suivant:

void init() { /* Called once, preload essential resources here. */ }
void update(double time) { /* Updates game/animation state using high resolution time. */ }
void render(double time) { /* Updates screen graphics using high resolution time. */ }

void run()
{
    double time;
    init();
    while (!done)
    {
        time = queryTime();
        update(time);
        render(time);
    }
}

Le temps est si important pour des animations fluides et de l'état de jeu de calculs. En code natif Windows, j'utilise QueryPerformanceCounter() et QueryPerformanceFrequency() à jouer le rôle de queryTime() dans chaque boucle de jeu et de passer le temps de mettre à jour/render. En Java, j'utilise System.nanoTime().

Ce qui est l'équivalent en JavaScript? Qui est, que certaines fonctions comme la queryTime() qui retourne une valeur de temps avec un haut degré de précision (sous-ordre de la milliseconde). De ce que j'ai entendu la meilleure précision que vous pouvez obtenir en JavaScript est d'environ 15 ms ... ce qui est horrible pour l'animation.

104voto

h3r3 Points 707

Presque tous les navigateurs modernes offrent une haute résolution de la minuterie. C'est la "Haute Résolution" standard du W3C: http://www.w3.org/TR/hr-time/#sec-DOMHighResTimeStamp.

Il vous permet d'obtenir un sous-ordre de la milliseconde précis horodatage par l'appel de la fenêtre.les performances.maintenant(). Cela renvoie d'un timbre de temps en ms, mais c'est un flotteur de sorte que vous obtenez toujours des sous-milliseond résolution.

Les navigateurs plus anciens peuvent encore mettre en œuvre un "préfixe" version de cette norme, par exemple, les navigateurs basés sur WebKit utilisé pour mettre en œuvre la fenêtre.les performances.webkitNow()

Voici un code que vous pouvez utiliser pour obtenir la précision timstamp et de secours à la norme de précision contraire:

if (window.performance.now) {
    console.log("Using high performance timer");
    getTimestamp = function() { return window.performance.now(); };
} else {
    if (window.performance.webkitNow) {
        console.log("Using webkit high performance timer");
        getTimestamp = function() { return window.performance.webkitNow(); };
    } else {
        console.log("Using low performance timer");
        getTimestamp = function() { return new Date().getTime(); };
    }
}

getTimestamp();

Notez que cette méthode gettimestamp() la fonction ne retourne pas une valeur qui représente la date/heure actuelle. La valeur retournée peut seulement être utilisé pour mesurer des périodes de temps (par soustraction de deux horodateurs). E. g.

var t1 = getTimestamp();
//... some other code
var t2 = getTimestamp();
console.log("Time delta: " + (t2 - t1));

11voto

mwcz Points 2520

Millisecondes sont le mieux que vous pouvez espérer pour en JavaScript. Et, comme vous l'avez dit, il n'est pas très précise. Voir Débordement de Pile question de la Microseconde calendrier en JavaScript.

timer.js vise à fournir à la microseconde résolution, mais il est uniquement disponible pour Google Chrome.

Mise à jour: timer.js ne pas soutenir la microseconde résolution. Il littéralement juste se multiplie à l'ordre de la milliseconde nombre par 1000.

Mise à jour 2: Voir @h3r3 la réponse ci-dessous. Il devrait probablement être choisi comme la réponse correcte.

Désolé, il n'y a pas de meilleures nouvelles!

10voto

katspaugh Points 6110

Au lieu de while (true) / setInterval , utilisez récursif requestAnimationFrame . Il fonctionnera plus facilement que les animations basées sur le timeout. Il fournit des horodatages si vous avez besoin que votre animation s'exécute sur un chemin plus lent .

6voto

Oleg Kikin Points 150

À partir de maintenant (25 février 2013), la qualité des temps de haute performance dans Chrome 24 est assez horrible.

 var old = 0; 

for (var i=0; i<10; i++) {
    var t = window.performance.now(); 
    var d = t - old; 
    old = t; 
    console.log(t + ' += ' +d); 
}
 

génère quelque chose comme ceci:

 609689.000000013 += 609689.000000013
609689.9999999441 += 0.9999999310821295
609689.9999999441 += 0
609689.9999999441 += 0
609689.9999999441 += 0
609690.9999999916 += 1.0000000474974513
609690.9999999916 += 0
609690.9999999916 += 0
609691.9999999227 += 0.9999999310821295
609691.9999999227 += 0
 

Ce qui montre que

1) L'échantillonnage se produit rarement

2) La précision est toujours d'environ 1 ms, pas dans la gamme des microsecondes.

2voto

Juan Mendes Points 31678

Voici ce que votre code devrait ressembler en JavaScript, afin de ne pas bloquer l'interface utilisateur et n'utilisez pas de fenêtre.requestAnimationFrame qui ne fonctionne pas de la croix-navigateur.

/* Called once, preload essential resources here. */
function init() {}

/* Updates game/animation state */
function update(time) {}

/* Updates screen graphics  */
function render(time) {}

window.onload = function()
{
    var time;
    var done = false;

    init();
    // Using setTimeout passing zero makes the animate function run
    // as soon as possible, but yielding first.
    setTimeout(animate, 0);

    function animate () {
        time = new Date();
        update(time);
        render(time);
        if (!done) {
            setTimeout(animate, 0);
        }
    }
}

Un problème avec cette approche est que l' animate() peut être appelé le plus souvent que l'écran est mis à jour (à 60 Hz, il ne sera pas mise à jour plus souvent que abot toutes les 16 ms), causant supplémentaires de rendu qui ne s'est jamais rendu à l'écran. C'est pourquoi vous devriez coller avec requestAnimationFrame si possible.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X