Animacje internetowe – element element.animate() jest teraz w Chrome 36

Brendan Kenny
Brendan Kenny

Animacje w internecie należały niegdyś do JavaScriptu. Jednak w miarę upowszechniania się w aplikacjach mobilnych animacje przenosiły się do CSS ze względu na składnię deklaratywną i optymalizacje, które były w stanie wykonać przeglądarki. 60 klatek na sekundę na urządzeniach mobilnych zawsze jest Twoim celem, dlatego warto nigdy nie wyjść poza to, co przeglądarki wiedzą, jak sprawnie wyświetlać reklamy.

Pojawia się coraz więcej narzędzi zwiększających efektywność animacji opartych na JavaScript, ale święty Graal stanowi połączenie animacji deklaratywnych i imperatywnych, w przypadku których decyzja o sposobie napisania animacji zależy od najczystszego kodu, a nie od tego, co jest możliwe w jednej, a nie w innej.

Animacje internetowe odpowiadają na to połączenie. Pierwsza jego część jest dostępna w Chrome 36 w formacie element.animate(). Ta nowa funkcja pozwala tworzyć animacje w samym języku JavaScript i uruchamiać je tak samo wydajnie jak dowolne animacje i przejścia CSS (od wersji Chrome 34 ten sam mechanizm animacji internetowych obsługuje wszystkie te metody).

Składnia jest prosta, a jej elementy powinny być dla Ciebie znajome, jeśli zdarzyło Ci się już korzystać z funkcji przejścia lub animacji w CSS:

element.animate([
    {cssProperty: value0},
    {cssProperty: value1},
    {cssProperty: value2},
    //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});

Największą zaletą tej nowej funkcji jest eliminacja wielu niezręcznych obręczy, przez które trzeba było wcześniej przeskakiwać, aby uzyskać płynną i bezproblemową animację.

Na przykład w zeszłorocznym roku Trasa Świętego Mikołaja zależało nam na tym, aby padał śnieg bez przerwy. Dlatego postanowiliśmy animować ten film za pomocą CSS, aby można było to zrobić tak wydajnie.

Chcieliśmy jednak dynamicznie określić położenie śniegu w poziomie w zależności od ekranu i wydarzeń występujących w samej scenie. Wysokość spadającego śniegu (wysokość okna przeglądarki użytkownika) oczywiście była widoczna dopiero po uruchomieniu. Musieliśmy więc użyć przejść CSS, ponieważ tworzenie animacji CSS w czasie ich działania szybko staje się skomplikowane (setki płatków śniegu oznaczają setki nowych reguł stylu).

Przyjęliśmy więc podejście, które powinno być Ci dobrze znane:

snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// wait a frame
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';

Klucz znajduje się w komentarzu „oczekuj na ramkę”. Aby rozpocząć przejście, przeglądarka musi potwierdzić, że element znajduje się w pozycji początkowej. Możesz to zrobić na kilka sposobów. Jednym z najpowszechniejszych sposobów jest odczytywanie z jednej z właściwości elementów, które wymuszają na przeglądarce obliczenie układu, i dzięki temu przed przejściem do pozycji końcowej wie, że element ma pozycję początkową. Dzięki tej metodzie możesz pogratulować sobie doskonałej wiedzy o przeglądarce, nie rezygnując przy tym z każdego naciśnięcia klawiszy.

Z kolei odpowiednik wywołania element.animate() nie mógłby być bardziej zrozumiały:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);

Jest znacznie więcej opcji. Animacje internetowe, podobnie jak ich odpowiedniki w stylu CSS, mogą być opóźnione i powtarzane:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
    duration: 1500,
    iterations: 10,
    delay: 300
});

AnimationPlayer

Komponent element.animate() zwraca obiekt AnimationPlayer, który w miarę pojawiania się kolejnych specyfikacji animacji będzie nabierał coraz większego znaczenia. Animacje utworzone w języku JavaScript i CSS będą powiązane z elementami AnimationPlayers, co pozwoli na ich płynne łączenie w ciekawy i przydatny sposób.

Na razie AnimationPlayer ma jednak tylko dwie funkcje, które są bardzo przydatne. Animację możesz anulować w dowolnym momencie, używając polecenia AnimationPlayer.cancel():

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();

Ku radości dla wszystkich, którzy w przeszłości próbowali zbudować system animacji oparty na animacjach CSS lub przejściach, Animacje internetowe zawsze uruchamiają odpowiednie zdarzenie po ich zakończeniu:

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
    console.log('per aspera ad terra!');
}

Wypróbuj

To wszystko w Chrome 36, a od dzisiaj do wersji beta! Jeśli chcesz wypróbować tę funkcję, popracuj nad implementacją natywną w Chrome 36. Można jednak skorzystać z kodu polyfill Animacji internetowych, który zapewnia znacznie większą część pełnej specyfikacji animacji internetowych w przypadku każdej z nowoczesnych, ponadczasowych przeglądarek.

Możesz zobaczyć demonstrację efektu śniegu, aby wypróbować zarówno natywną wersję element.animate(), jak i polyfill.

Powiedz nam, co myślisz

Jest to jednak tylko podgląd tego, co pojawi się w przyszłości. Publikujemy je specjalnie po to, by od razu uzyskać opinie deweloperów. Nie wiemy jeszcze, czy w pełni wykorzystaliśmy wszystkie przypadki użycia, czy też dopracowaliśmy wszystkie istniejące interfejsy API pod kątem animacji. Jedynym sposobem, w jaki możemy to stwierdzić i zapewnić odpowiednie działanie, jest wypróbowanie tej funkcji przez deweloperów i podzielenie się nią z nami.

Komentarze do tego posta są oczywiście cenne, a komentarze dotyczące standardu można zaadresować do grup roboczych CSS i SVG za pomocą listy adresowej public-fx.

Aktualizacja z października 2014 r.: Chrome 39 dodaje obsługę kilku dodatkowych metod związanych z kontrolą odtwarzania, takich jak play(), pause() i reverse(). Umożliwia też przejście do określonego punktu na osi czasu animacji za pomocą właściwości currentTime. Działanie tej funkcji możesz zobaczyć w nowej wersji demonstracyjnej.

Dziękujemy Addy Osmani i Max Heinritz za pomoc przy tym poście.