Jeśli używasz programu requestAnimationFrame
, podoba Ci się, że Twoje farby są zsynchronizowane z częstotliwością odświeżania ekranu, co pozwala uzyskać najlepszą jakość animacji. Poza tym gdy użytkownicy przełączają się na inną kartę, oszczędzają szum wentylatora procesora i energię baterii.
Wkrótce nastąpi jednak zmiana w części interfejsu API. Sygnatura czasowa przekazywana do funkcji wywołania zwrotnego zmienia się z typowej sygnatury czasowej (takiej jak Date.now()
) na pomiar w wysokiej rozdzielczości z milisekundami zmiennoprzecinkowym od otwarcia strony. Jeśli używasz tej wartości, musisz zaktualizować kod, zgodnie z poniższym wyjaśnieniem.
Dla jasności – oto co mówię:
// assuming requestAnimationFrame method has been normalized for all vendor prefixes..
requestAnimationFrame(function(timestamp){
// the value of timestamp is changing
});
Jeśli używasz typowej podkładki requestAnimFrame
podanej tutaj, nie używasz wartości sygnatury czasowej. Jesteś na dobrej drodze. :)
Dlaczego
Dlaczego? Cóż, rAF pomaga uzyskać idealną prędkość 60 klatek na sekundę, która odpowiada idealnej wartości 60 klatek na sekundę, czyli 16,7 ms na klatkę. Pomiar w milisekundach oznacza, że z dokładnością do wszystkich danych, które chcemy obserwować i kierować, z dokładnością wynosi 1/16.
Jak widać powyżej, niebieski pasek reprezentuje maksymalny czas do wykonania całej pracy przed namalowaniem nowej klatki (przy 60 kl./s). Prawdopodobnie robisz więcej niż 16 czynności, ale dzięki całkowitym wymiarom w milisekundach możesz tylko planować i mierzyć postępy. To za mało.
Minutnik w wysokiej rozdzielczości rozwiązuje ten problem, pokazując znacznie dokładniejsze wartości:
Date.now() // 1337376068250
performance.now() // 20303.427000007
Licznik w wysokiej rozdzielczości jest obecnie dostępny w Chrome jako window.performance.webkitNow()
. Ta wartość zazwyczaj jest równa nowej wartości argumentu przekazanej do wywołania zwrotnego rAF. Gdy specyfikacja pójdzie dalej pod względem standardów, metoda usunie prefiks i będzie dostępna na platformie performance.now()
.
Zwróć uwagę, że 2 powyższe wartości znacznie różnią się rzędami wielkości. performance.now()
to wartość mierzona w milisekundach w przeliczeniu zmiennoprzecinkowym od momentu rozpoczęcia wczytywania danej strony (performance.navigationStart
, aby była dokładna).
Używany
Głównym problemem przy przycinaniu są biblioteki animacji korzystające z tego wzorca projektowego:
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));
}
Zmiana, która pomoże Ci go poprawić, jest dość prosta... Powiększ startTime
i now
, aby używać window.performance.now()
.
this.startTime = window.performance.now ?
(performance.now() + performance.timing.navigationStart) :
Date.now();
Jest to dość naiwna implementacja, ponieważ nie korzysta z metody now()
z prefiksem i zakłada obsługę Date.now()
, której nie ma w IE8.
Wykrywanie funkcji
Jeśli nie korzystasz z powyższego wzorca i chcesz tylko sprawdzić, jaką wartość wywołania zwrotnego otrzymujesz, skorzystaj z tej techniki:
requestAnimationFrame(function(timestamp){
if (timestamp < 1e12){
// .. high resolution timer
} else {
// integer milliseconds since unix epoch
}
// ...
Sprawdzanie if (timestamp < 1e12)
to szybki test sprawdzający, z jaką liczbą mamy do czynienia. Technicznie rzecz biorąc, taki wynik może być fałszywy, ale tylko wtedy, gdy strona jest otwarta nieprzerwanie przez 30 lat. Jednak nie jesteśmy w stanie sprawdzić, czy jest to liczba zmiennoprzecinkowa (a nie liczba całkowita). Jeśli poprosisz o ustawienie wystarczającej liczby liczników czasu w wysokiej rozdzielczości, w pewnym momencie uzyskasz wartości całkowite.
Planujemy wprowadzić tę zmianę w Chrome 21, więc jeśli już korzystasz z tego parametru wywołania zwrotnego, nie zapomnij zaktualizować swojego kodu.