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 inne.

Kevin Ellis
Kevin Ellis

Data publikacji: 27 maja 2020 r.

Animacje, gdy są używane prawidłowo, poprawiają postrzeganie i zapamiętywanie marki przez użytkowników oraz pomagają im w działaniach i nawigacji w aplikacji, zapewniając kontekst w przestrzeni cyfrowej.

Interfejs Web Animations API to narzędzie, które umożliwia deweloperom tworzenie animacji imperatywnej za pomocą JavaScriptu. Został on 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 po raz pierwszy trafił do Chromium w wersji 36, lipiec 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

Tworzenie animacji za pomocą interfejsu Web Animations API powinno być całkiem znajome, jeśli korzystasz z reguł @keyframe. Najpierw musisz utworzyć obiekt kluczowego klatki. Jak w CSS może 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;
}

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ść używania efektów w sekwencji i większą kontrolę nad stanem odtwarzania.

Powyżej 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 przenikania usuń kopię.

sterowanie animacjami za pomocą obietnic;

W Chromium 84 masz teraz 2 metody, które można stosować z obietnicami: animation.readyanimation.finished.

  • animation.ready pozwala na oczekiwanie na zastosowanie oczekujących zmian (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 potomnego:

Stosuję przekształcenia i przezroczystość do otwierającego 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ą funkcji animation.finished.then() przed wykonaniem następnego zestawu animacji w łańcuchu. W ten sposób animacje będą pojawiać się w kolejności, 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 trudno byłoby to odtworzyć, zwłaszcza w przypadku stosowania 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.

Korzystając z .reverse(), możesz utworzyć płynną, odwróconą animację, która została pokazana w poprzedniej części prezentacji. Dzięki temu możesz stworzyć bardziej płynną i kontekstową interakcję z oknem modalnym.

Przycisk otwierania i zamykania modalnego okna po kliknięciu. Zobacz prezentację o zakłóceniu

Możesz utworzyć 2 animowane animacje (openModal i przekształcenie przezroczystości w wierszu), 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 prezentację o zakłóceniu
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. Obsługa myszy wykonuje tutaj 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żące przejście zostaje przerwane i tworzy się nowe.

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. Ukoń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 Glitch
elem.addEventListener('mousemove', evt => {
  rectangle.animate(
    { transform: translate(${evt.clientX}px, ${evt.clientY}px) },
    { duration: 500, fill: 'forwards' }
  );
});

Za każdym razem, gdy mysz się porusza, przeglądarka ponownie oblicza położenie każdej piłki na szlaku komety i tworzy animację w tym nowym punkcie. Przeglądarka wie teraz, czy usunąć stare animacje (włączać zastępowanie), gdy:

  1. Animacja została zakończona.
  2. W kolejności złożonej znajduje się co najmniej jedna animacja, która została już zakoń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 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 bazowego oraz wszystkich animacji elementu w kolejności złożonej.
  • animation.persist() oznacza, że animacji nie można zastąpić.

Gładsze animacje dzięki trybom złożonym

Dzięki interfejsowi Web Animations API możesz teraz ustawić tryb złożony animacji, co oznacza, że oprócz domyślnego trybu „zastąp” mogą się one sumować lub agregować. Tryby złożone pozwalają programistom tworzyć różne animacje i kontrolować sposób łączenia efektów. Obsługiwane są teraz 3 tryby kompozytowe: 'replace' (domyślny), 'add''accumulate'.

Gdy tworzysz animacje, 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 złożonym. Zobacz wersję demonstracyjną na Glitch

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 daje w efekcie końcowy stan rotate(720deg) scale(1.96). 'accumulate' łączy przekształcenia, co daje w wyniku 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 dwoma złożonymi animacjami. Zobacz demonstrację problemu

Tutaj skomponowano 2 animacje top. Pierwszym z nich jest makroanimacja, w którym menu jest przesuwane o pełną wysokość o pełną wysokość w celu wysuwania się z góry strony, a druga – mikroanimacja – powoduje małe odbicie ekranu w momencie dotknięcia ekranu. 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

Wszystkie te funkcje stanowią ekscytujące dodatki do animacji we współczesnych przeglądarkach, a wkrótce zostaną dodane kolejne. Aby dowiedzieć się więcej o nadchodzących zmianach, zapoznaj się z tymi specyfikacjami: