Если вы использовали requestAnimationFrame
вам нравилось видеть, как ваши краски синхронизируются с частотой обновления экрана, что приводит к максимально возможной высококачественной анимации. Кроме того, вы экономите шум вентилятора процессора и расход заряда батареи ваших пользователей, когда они переключаются на другую вкладку.
Однако скоро будут внесены изменения в часть API . Метка времени, передаваемая в вашу функцию обратного вызова, меняется с типичной метки времени, похожей на Date.now()
на измерение миллисекунд с плавающей запятой с высоким разрешением с момента открытия страницы. Если вы используете это значение, вам нужно будет обновить свой код , основываясь на объяснении ниже.
Чтобы внести ясность, вот о чем я говорю:
// assuming requestAnimationFrame method has been normalized for all vendor prefixes..
requestAnimationFrame(function(timestamp){
// the value of timestamp is changing
});
Если вы используете общую прокладку requestAnimFrame
представленную здесь , вы не используете значение метки времени. Вы сошли с крючка. :)
Почему
Почему? Что ж, rAF помогает вам получить идеальные 60 кадров в секунду, а 60 кадров в секунду соответствуют 16,7 мс на кадр. Но измерение целыми миллисекундами означает, что у нас есть точность 1/16 для всего, что мы хотим наблюдать и нацеливаться.
Как вы можете видеть выше, синяя полоса представляет максимальное количество времени, которое вам понадобится, чтобы выполнить всю работу, прежде чем рисовать новый кадр (со скоростью 60 кадров в секунду). Вероятно, вы делаете более 16 действий, но с целыми миллисекундами у вас есть возможность планировать и измерять только с этими очень короткими приращениями. Это недостаточно хорошо.
Таймер высокого разрешения решает эту проблему, предоставляя гораздо более точные цифры:
Date.now() // 1337376068250
performance.now() // 20303.427000007
Таймер высокого разрешения в настоящее время доступен в Chrome как window.performance.webkitNow()
, и это значение обычно равно новому значению аргумента, передаваемому в обратный вызов rAF. Как только спецификация пройдет дальше по стандартам, метод уберет префикс и станет доступен через performance.now()
.
Вы также заметите, что два приведенных выше значения различаются на много порядков. performance.now()
— это измерение миллисекунд с плавающей запятой с момента начала загрузки конкретной страницы (точнее, performance.navigationStart
).
В использовании
Ключевой проблемой, которую обрезают, являются библиотеки анимации, использующие этот шаблон проектирования:
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));
}
Отредактировать это довольно просто... увеличьте startTime
и now
используйте window.performance.now()
.
this.startTime = window.performance.now ?
(performance.now() + performance.timing.navigationStart) :
Date.now();
Это довольно наивная реализация, она не использует метод now()
с префиксом, а также предполагает поддержку Date.now()
, которой нет в IE8.
Обнаружение функций
Если вы не используете приведенный выше шаблон и просто хотите определить, какой тип значения обратного вызова вы получаете, вы можете использовать этот метод:
requestAnimationFrame(function(timestamp){
if (timestamp < 1e12){
// .. high resolution timer
} else {
// integer milliseconds since unix epoch
}
// ...
Проверка того, является if (timestamp < 1e12)
быстрым тестом на утиную реакцию, чтобы увидеть, с каким большим числом мы имеем дело. Технически это может быть ложное срабатывание, но только если веб-страница открыта непрерывно в течение 30 лет. Но мы не можем проверить, является ли это числом с плавающей запятой (а не преобразованным в целое число). Попросите таймеры с достаточно высоким разрешением, и в какой-то момент вы обязательно получите целочисленные значения .
Мы планируем внести это изменение в Chrome 21, поэтому, если вы уже используете этот параметр обратного вызова, обязательно обновите свой код!