Si vous utilisez requestAnimationFrame, vous avez pu constater que vos peintures sont synchronisées avec la fréquence d'actualisation de l'écran, ce qui permet d'obtenir des animations d'une fidélité optimale. De plus, vous évitez à vos utilisateurs d'entendre le bruit du ventilateur du processeur et d'user la batterie lorsqu'ils passent à un autre onglet.
Une partie de l'API va toutefois être modifiée. Le code temporel transmis à votre fonction de rappel passe d'un code temporel classique de type Date.now() à une mesure haute résolution de millisecondes à virgule flottante depuis l'ouverture de la page. Si vous utilisez cette valeur, vous devrez mettre à jour votre code, en fonction de l'explication ci-dessous.
Pour être plus 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 courant fourni ici, vous n'utilisez pas la valeur du code temporel. Vous êtes tiré d'affaire. :)
Pourquoi
Pourquoi ? rAF vous aide à obtenir les 60 FPS idéaux, ce qui correspond à 16,7 ms par image. Mais mesurer avec des millisecondes entières signifie que nous avons 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 une nouvelle image (à 60 FPS). Vous effectuez probablement plus de 16 opérations, mais avec des millisecondes entières, vous ne pouvez planifier et mesurer que par incréments très importants. Ce n'est pas suffisant.
Le minuteur haute résolution résout ce problème en fournissant un chiffre beaucoup plus précis :
Date.now() // 1337376068250
performance.now() // 20303.427000007
Le minuteur haute résolution est actuellement disponible dans Chrome sous la forme window.performance.webkitNow(), et cette valeur est généralement égale à la nouvelle valeur d'argument transmise au rappel rAF. Une fois que la spécification aura progressé dans les normes, 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() est une mesure en millisecondes à virgule flottante depuis le début du chargement de cette page (performance.navigationStart pour être précis).
Utilisées
Le principal problème qui se pose 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));
}
Pour résoudre ce problème, il suffit d'augmenter 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, qui n'utilise pas de méthode now() préfixée et qui suppose également la compatibilité avec Date.now(), ce qui n'est pas le cas dans IE8.
Détection de caractéristiques
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 voir à quel point le nombre est élevé. Techniquement, il pourrait s'agir d'un faux positif, mais seulement si une page Web est ouverte en continu pendant 30 ans. Cependant, nous ne pouvons pas tester s'il s'agit d'un nombre à virgule flottante (plutôt que d'un nombre entier). Si vous demandez suffisamment de minuteurs haute résolution, vous obtiendrez forcément des valeurs entières à un moment donné.
Nous prévoyons de déployer cette modification dans Chrome 21. Par conséquent, si vous utilisez déjà ce paramètre de rappel, veillez à mettre à jour votre code.