Si vous avez utilisé requestAnimationFrame
, vous avez apprécié de voir vos peintures synchronisées avec la fréquence d'actualisation de l'écran, ce qui a généré les animations les plus haute fidélité possible. De plus, vous économisez le bruit du ventilateur du processeur et la batterie de vos utilisateurs lorsqu'ils passent à un autre onglet.
Une partie de l'API va toutefois être modifiée. L'horodatage transmis à votre fonction de rappel passe d'un code temporel Date.now()
typique à une mesure haute résolution en millisecondes à virgule flottante depuis l'ouverture de la page. Si vous utilisez cette valeur, vous devrez mettre à jour votre code, conformément à l'explication ci-dessous.
Pour être clair, voici ce dont je parle:
// assuming requestAnimationFrame method has been normalized for all vendor prefixes..
requestAnimationFrame(function(timestamp){
// the value of timestamp is changing
});
Si vous utilisez le shim requestAnimFrame
commun fourni ici, vous n'utilisez pas la valeur d'horodatage. Vous n'êtes pas concerné. :)
Pourquoi
Pourquoi ? Eh bien, rAF vous aide à atteindre les 60 FPS idéaux, ce qui correspond à 16,7 ms par image. Toutefois, mesurer en millisecondes entières signifie que nous disposons d'une précision de 1/16 pour tout ce que nous voulons observer et cibler.

Comme vous pouvez le voir ci-dessus, la barre bleue représente le temps maximal dont vous disposez pour effectuer tout votre travail avant de peindre un nouveau frame (à 60 FPS). Vous effectuez probablement plus de 16 tâches, mais avec des millisecondes entières, vous ne pouvez planifier et mesurer que ces incréments très importants. Ce n'est pas suffisant.
Le Minuteur haute résolution résout ce problème en fournissant une valeur beaucoup plus précise:
Date.now() // 1337376068250
performance.now() // 20303.427000007
Le minuteur haute résolution est actuellement disponible dans Chrome sous la forme window.performance.webkitNow()
. Cette valeur est généralement égale à la nouvelle valeur d'argument transmise au rappel rAF. Une fois que la spécification aura évolué, la méthode supprimera le préfixe et sera disponible via performance.now()
.
Vous remarquerez également que les deux valeurs ci-dessus sont très différentes. performance.now()
correspond à une mesure en millisecondes à virgule flottante depuis le début du chargement de cette page spécifique (performance.navigationStart
, plus précisément).
Utilisées
Le principal problème concerne les bibliothèques d'animation qui utilisent ce modèle de conception:
function MyAnimation(duration) {
this.startTime = Date.now();
this.duration = duration;
requestAnimFrame(this.tick.bind(this));
}
MyAnimation.prototype.tick = function(time) {
var now = Date.now();
if (time > now) {
this.dispatchEvent("ended");
return;
}
...
requestAnimFrame(this.tick.bind(this));
}
La correction est assez simple : modifiez startTime
et now
pour utiliser window.performance.now()
.
this.startTime = window.performance.now ?
(performance.now() + performance.timing.navigationStart) :
Date.now();
Il s'agit d'une implémentation assez naïve. Elle n'utilise pas de méthode now()
préfixée et suppose également la prise en charge de Date.now()
, qui n'est pas disponible dans IE8.
Détection de fonctionnalités
Si vous n'utilisez pas le modèle ci-dessus et que vous souhaitez simplement identifier le type de valeur de rappel que vous obtenez, vous pouvez utiliser cette technique:
requestAnimationFrame(function(timestamp){
if (timestamp < 1e12){
// .. high resolution timer
} else {
// integer milliseconds since unix epoch
}
// ...
La vérification de if (timestamp < 1e12)
est un test rapide pour déterminer la taille du nombre avec lequel nous travaillons. Techniquement, il peut s'agir d'un faux positif, mais uniquement si une page Web est ouverte en continu pendant 30 ans. Toutefois, nous ne pouvons pas vérifier s'il s'agit d'un nombre à virgule flottante (plutôt que d'un entier arrondi). Demandez suffisamment de minuteurs haute résolution, et vous obtiendrez à un moment donné des valeurs entières.
Nous prévoyons de déployer cette modification dans Chrome 21. Si vous utilisez déjà ce paramètre de rappel, veillez à mettre à jour votre code.