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

Animacje w internecie były kiedyś domeną JavaScriptu, ale wraz z rozwojem urządzeń mobilnych przeniesiono je do CSS ze względu na deklaratywną składnię i możliwości optymalizacji, jakie oferuje ten język. Ponieważ 60 FPS na urządzeniach mobilnych to zawsze cel, warto pamiętać, aby nigdy nie przekraczać limitów, które przeglądarki potrafią efektywnie wyświetlać.

Pojawia się coraz więcej narzędzi, które zwiększają wydajność animacji opartych na JavaScript, ale prawdziwym wybawieniem byłoby ujednolicenie deklaratywnych i imperatywnych animacji, w których przypadku decyzja o sposobie ich tworzenia byłaby podejmowana na podstawie tego, co jest najczystszym kodem, a nie tego, co jest możliwe w jednym przypadku, a czego nie można zrobić w drugim.

Animacje internetowe mogą sprostać temu wyzwaniu. Pierwsza część tej funkcji została wprowadzona w Chrome 36 w postaci element.animate(). Ta nowa funkcja umożliwia tworzenie animacji wyłącznie w JavaScript i wykonywanie jej tak samo wydajnie jak animacji lub przejść CSS (w fakcie od wersji 34 Chrome wszystkie te metody są obsługiwane przez ten sam mechanizm animacji internetowych).

Składnia jest prosta, a jej części powinny być Ci znane, jeśli kiedykolwiek pisałeś/pisałaś animację lub przejście CSS:

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

Największą zaletą tej nowej funkcji jest wyeliminowanie wielu niewygodnych rozwiązań, które wcześniej musieliśmy stosować, aby uzyskać płynną animację bez zacięć.

Na przykład w zeszłym roku w ramach śledzenia Świętego Mikołaja chcieliśmy, aby śnieg padał bez przerwy. Zdecydowaliśmy się na animację za pomocą CSS, aby zrobić to efektywnie.

Chcieliśmy jednak wybrać pozycję poziomą śniegu dynamicznie na podstawie ekranu i zdarzeń występujących w samej scenie. Oczywiście wysokość śniegu (wysokość okna przeglądarki użytkownika) nie była znana, dopóki nie uruchomiliśmy animacji. Oznaczało to, że musieliśmy użyć przejść CSS, ponieważ tworzenie animacji CSS w czasie wykonywania szybko staje się skomplikowane (a setki płatków śniegu oznaczają setki nowych reguł stylizacji).

Dlatego zastosowaliśmy następujące podejście, które powinno być Ci 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)';

Kluczem jest komentarz „wait a frame”. 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 najczęstszych sposobów jest odczytywanie z jednej z właściwości elementu, która zmusza przeglądarkę do obliczenia układu, dzięki czemu wie ona, że element ma pozycję początkową przed przejściem do pozycji końcowej. Dzięki tej metodzie możesz pochwalić się swoją wiedzą na temat wewnętrznej budowy przeglądarki, ale przy każdym naciśnięciu klawisza będziesz czuć się źle.

Natomiast odpowiednia funkcja element.animate() jest bardzo jasna i dokładnie określa, co ma się stać:

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

Dostępnych jest wiele innych opcji. Podobnie jak w przypadku animacji CSS, animacje internetowe mogą być opóźniane i powtarzane:

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

AnimationPlayer

Funkcja element.animate() zwraca obiekt AnimationPlayer, który będzie coraz ważniejszy wraz z uzyskiwaniem dostępu do kolejnych specyfikacji animacji internetowych. Zarówno animacje utworzone za pomocą JavaScript, jak i CSS będą miały powiązane odtwarzacze animacji, co pozwoli na ich płynne łączenie w przydatne i ciekawe sposoby.

Obecnie AnimationPlayer ma tylko 2 funkcje, ale obie są bardzo przydatne. W każdej chwili możesz anulować animację, korzystając z elementu 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();

Na szczęście wszystkich, którzy w przeszłości próbowali tworzyć system animacji na podstawie animacji lub przejść CSS, animacje webowe zawsze wywołują zdarzenie po 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

Wszystkie te funkcje są dostępne w Chrome 36, który dziś przechodzi do wersji beta. Jeśli chcesz to wypróbować, użyj natywnej implementacji w Chrome 36. Dostępna jest jednak biblioteka polyfill Web Animations, która udostępnia znacznie większą część pełnej specyfikacji Web Animations w dowolnej nowoczesnej przeglądarce evergreen.

Dostępne jest demo efektu śniegu, które możesz wypróbować, korzystając zarówno z natywnej wersji element.animate(), jak i z polyfill.

Powiedz nam, co myślisz

To wstępna wersja tego, co jest w planach, i jest udostępniana, abyśmy mogli od razu uzyskać opinie programistów. Nie jesteśmy jeszcze pewni, czy uwzględniliśmy wszystkie przypadki użycia ani czy wygładziliśmy wszystkie ostre krawędzie obecnych interfejsów API dotyczących animacji. Jedynym sposobem, abyśmy mogli się tego dowiedzieć i dobrze to zrobić, jest wypróbowanie przez deweloperów i przekazanie nam opinii.

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

Aktualizacja z października 2014 r.: w Chrome 39 dodano obsługę kilku dodatkowych metod związanych z sterowaniem odtwarzaniem, takich jak play(), pause()reverse(). Umożliwia też przejście do określonego punktu na osi czasu animacji za pomocą właściwości currentTime. Jak działa ta funkcja, możesz zobaczyć w tym nowym filmie demonstracyjnym.

Dziękujemy Addie Osmani i Maxowi Heinritzowi za pomoc w przygotowaniu tego posta.