Ulepszenia interfejsu Web Animations API w Chromium 84

sterowanie animacjami za pomocą obietnic, poprawa wydajności dzięki wymiennym animacjom, płynniejsze animacje dzięki trybom kompozytowym i nie tylko.

Data publikacji: 27 maja 2020 r.

Właściwie użyte animowane elementy poprawiają postrzeganie i zapamiętywanie marki przez użytkowników, kierują ich działania oraz pomagają im w poruszaniu się po aplikacji – zapewniają kontekst w przestrzeni cyfrowej.

Interfejs Web Animations API to narzędzie, które umożliwia deweloperom tworzenie wymagających animacji w języku JavaScript. Został napisany, aby wspierać implementacje animacji i przejść CSS oraz umożliwić tworzenie nowych efektów, a także komponowanie i synchronizowanie efektów istniejących.

Chociaż FirefoxSafari wdrożyły już pełny zestaw funkcji ze specyfikacji, Chromium 84 wprowadza do Chrome i Edge wiele funkcji, które wcześniej nie były obsługiwane, umożliwiając współpracę między przeglądarkami.

Interfejs Web Animations API został po raz pierwszy wprowadzony w Chromium w wersji 36 w lipcu 2014 r. Specyfikacja zostanie teraz ukończona w wersji 84, która zostanie wydana w lipcu 2020 r.
Długa historia interfejsu Web Animations API w Chromium.

Pierwsze kroki

Jeśli korzystasz z reguł @keyframe, tworzenie animacji za pomocą interfejsu Web Animations API powinno być bardzo znajome. Najpierw musisz utworzyć obiekt kluczowego klatki. W CSS może to wyglądać tak:

@keyframes openAnimation {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}

wyglądałby w JavaScriptzie tak:

const openAnimation = [
  { transform: 'scale(0)' },
  { transform: 'scale(1)' },
];

Gdzie ustawiasz parametry animacji w CSS:

.modal {
  animation: openAnimation 1s 1 ease-in;
}

ustawiasz w JS:

document.querySelector('.modal').animate(
    openAnimation, {
      duration: 1000, // 1s
      iterations: 1, // single iteration
      easing: 'ease-in' // easing function
    }
);

Ilość kodu jest mniej więcej taka sama, ale JavaScript daje Ci kilka supermocy, których nie ma sam CSS. Obejmuje to możliwość sekwencyjności efektów i większą kontrolę nad stanami odtwarzania.

element.animate()

Jednak po aktualizacji interfejs Web Animations API nie jest już ograniczony do animacji utworzonych za pomocą element.animate(). Możemy też manipulować animacjami i przejęciami CSS.

getAnimations() to metoda, która zwraca wszystkie animacje elementu niezależnie od tego, czy została utworzona za pomocą element.animate(), czy za pomocą reguł CSS (animacja lub przejście CSS). Oto przykład:

Najpierw "get" kluczowe klatki przejścia, aby określić, skąd pochodzi przejście. Następnie utwórz 2 nowe animacje przezroczystości, aby włączyć efekt przejścia. Po zakończeniu przejścia między obrazami usuwasz kopię.

Jak sterować animacjami za pomocą obietnic

W Chromium 84 są teraz dostępne 2 metody, które można stosować z obietnicami: animation.readyanimation.finished.

  • animation.ready pozwala poczekać, aż zmiany zostaną wprowadzone (czyli przełączanie się między metodami sterowania odtwarzaniem, takimi jak odtwarzanie i wstrzymywanie).
  • animation.finished umożliwia wykonywanie niestandardowego kodu JavaScript po zakończeniu animacji.

Wróćmy do naszego przykładu i utwórzmy sterowany łańcuch animacji za pomocą animation.finished. Tutaj masz przekształcenie pionowe (scaleY), a potem poziome (scaleX) i zmianę krycia elementu podrzędnego:

Stosowanie przekształceń i przezroczystości do otwieranego elementu modalnego. Zobacz wersję demonstracyjną w Codepen
const transformAnimation = modal.animate(openModal, openModalSettings);
transformAnimation.finished.then(() => { text.animate(fadeIn, fadeInSettings)});

Te animacje zostały połączone za pomocą elementu animation.finished.then() przed wykonaniem następnego zestawu animacji w łańcuchu. W ten sposób animacje będą pojawiać się w porządku, a efekty będziesz stosować nawet do różnych elementów docelowych z różnymi ustawieniami (np. prędkości i łatwości).

W CSS byłoby to trudne do odtworzenia, zwłaszcza przy stosowaniu niepowtarzalnych, ale uporządkowanych animacji do wielu elementów. Musisz użyć @keyframe, określić prawidłowe wartości procentowe czasu trwania animacji i użyć animation-delay przed uruchomieniem animacji w sekwencji.

Przykład: odtwarzanie, wstrzymywanie i odtwarzanie wstecz

To, co może się otworzyć, powinno się zamknąć. Na szczęście od wersji Chromium 39 interfejs Web Animations API umożliwia odtwarzanie, wstrzymywanie i odwracanie animacji.

Możesz wziąć animację wyświetlaną wcześniej i zastosować do niej płynną, odwróconą animację, klikając ponownie przycisk .reverse(). Dzięki temu możesz stworzyć bardziej płynną i kontekstową interakcję z oknem modalnym.

Przycisk otwierania i zamykania modalnego okna po kliknięciu. Demo na CodePen

Możesz utworzyć 2 animowane elementy (openModal i przekształcenie przejrzystości w ramach), a potem wstrzymać jedną z nich, opóźniając ją do czasu zakończenia drugiej. Możesz wtedy użyć obietnic, aby poczekać, aż wszystkie zostaną wykonane, zanim zaczniesz odtwarzać. Na koniec możesz sprawdzić, czy flaga jest ustawiona, a następnie odwrócić każdą animację.

Przykład: interakcje dynamiczne z częściowymi klatkami kluczowymi

Przykład kierowania na odbiorców, w którym kliknięcie myszką zmienia animację na nową lokalizację. Zobacz wersję demonstracyjną na CodePen
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
    {duration: 1000, fill: 'forwards'});

W tym przykładzie jest tylko 1 klatka kluczowa i nie ma określonej pozycji początkowej. Oto przykład użycia częściowych klatek kluczowych. Handler myszy wykonuje tu kilka czynności: ustawia nową lokalizację końcową i uruchamia nową animację. Nowa pozycja początkowa jest określana na podstawie bieżącej pozycji podstawowej.

Nowe przejścia mogą być uruchamiane, gdy istniejące są nadal aktywne. Oznacza to, że bieżąca zmiana jest przerywana i tworzy się nowa.

Poprawa wydajności dzięki zastępowaniu animacji

Podczas tworzenia animacji na podstawie zdarzeń, takich jak 'mousemove', za każdym razem tworzona jest nowa animacja, co może szybko zużywać pamięć i obniżać wydajność. Aby rozwiązać ten problem, w wersji Chromium 83 wprowadzono zastępowalne animacje, które umożliwiają automatyczne czyszczenie. Zakończone animacje są oznaczane jako zastępowalne i automatycznie usuwane, jeśli zostaną zastąpione przez inną ukończoną animację. Na przykład:

Ślad komety animuje się podczas poruszania myszką. Zobacz wersję demonstracyjną na CodePen
elem.addEventListener('mousemove', evt => {
  rectangle.animate(
    { transform: translate(${evt.clientX}px, ${evt.clientY}px) },
    { duration: 500, fill: 'forwards' }
  );
});

Za każdym razem, gdy przesuniesz mysz, przeglądarka ponownie oblicza położenie każdej kuli w śladzie komety i tworzy animację dla tego nowego punktu. Przeglądarka wie teraz, aby usuwać stare animacje (umożliwiając zastąpienie), gdy:

  1. Animacja została zakończona.
  2. W porządku złożonym znajduje się co najmniej 1 animacja, która również jest ukończona.
  3. Nowe animacje mają te same właściwości.

Możesz sprawdzić, ile animacji zostało zastąpionych, zliczając licznik przy każdej usuniętej animacji i używając anim.onremove, aby go uaktywnić.

Istnieje kilka dodatkowych właściwości i metod, które pozwolą Ci jeszcze lepiej kontrolować animację:

  • animation.replaceState umożliwia śledzenie, czy animacja jest aktywna, trwała czy usunięta.
  • animation.commitStyles() aktualizuje styl elementu na podstawie stylu podstawowego wraz ze wszystkimi animacjami elementu w kolejności złożonej.
  • animation.persist() oznacza, że animacji nie można zastąpić.

płynniejsze animacje dzięki trybom złożonym;

Dzięki interfejsowi Web Animations API możesz teraz ustawiać tryb złożony animacji, co oznacza, że mogą one być dodawane lub kumulowane, oprócz domyślnego trybu „zastępowania”. Tryby kompozytowe umożliwiają deweloperom tworzenie różnych animacji i kontrolowanie sposobu łączenia efektów. Obsługiwane są teraz 3 tryby kompozytowe: 'replace' (domyślny), 'add''accumulate'.

Gdy tworzysz kompozycję animacji, deweloper może napisać krótkie, odrębne efekty i zobaczyć je połączone. W tym przykładzie do każdego pola stosujemy klatkę kluczową rotacji i skali, a jedyną zmianą jest tryb kompozytowy dodany jako opcja:

Demonstracja pokazująca domyślny, dodawanie i akumulację w trybie kompozytowym. Zobacz wersję demonstracyjną na CodePen

W domyślnym trybie składania 'replace' końcowa animacja zastępuje właściwość transform i kończy się w punkcie rotate(360deg) scale(1.4). W przypadku 'add' kompozycja dodaje obrót i mnoży skalę, co powoduje, że ostateczny stan to rotate(720deg) scale(1.96). Funkcja 'accumulate' łączy przekształcenia, co daje w wyniku funkcję rotate(720deg) scale(1.8). Więcej informacji o szczegółach tych trybów złożonych znajdziesz w specyfikacji animacji internetowych w sekcji Enumeracje CompositeOperation i CompositeOperationOrAuto.

Zapoznaj się z tym przykładem elementu interfejsu użytkownika:

Menu rozwijane z efektem odbicia, które ma 2 składane animacje. Zobacz wersję demonstracyjną na CodePen

Tutaj skomponowano 2 animacje top. Pierwsza to makroanimacja, która przesuwa menu w dół o pełną wysokość menu jako efekt przesuwania od góry strony. Druga to mikroanimacja, która powoduje niewielkie odbicie, gdy menu dociera do dołu. Korzystanie z trybu złożonego 'add' umożliwia płynniejsze przejście.

const dropDown = menu.animate(
    [
      { top: `${-menuHeight}px`, easing: 'ease-in' },
      { top: 0 }
    ], { duration: 300, fill: 'forwards' });

  dropDown.finished.then(() => {
    const bounce = menu.animate(
      [
        { top: '0px', easing: 'ease-in' },
        { top: '10px', easing: 'ease-out' },
        { ... }
      ], { duration: 300, composite: 'add' });
  });

Co dalej z interfejsem Web Animations API

To ekscytujące dodatki do możliwości animacji w dzisiejszych przeglądarkach. Jeszcze więcej funkcji jest w drodze. Aby dowiedzieć się więcej o przyszłych specyfikacjach, zapoznaj się z tymi dokumentami: