Zwiększ atrakcyjność animacji w swojej aplikacji internetowej
TL;DR: Worklet animacji umożliwia pisanie imperatywnych animacji, które uruchamiają się z fabryczną liczbą klatek, co zapewnia dodatkową płynność, Sprawia, że animacje są bardziej odporne na zatkanie w głównym wątku i można je kliknąć. do przewijania, a nie do czasu. Worklet animacji jest w Chrome Canary (za „Eksperymentalne funkcje platformy internetowej” flaga) i planujemy wersję próbną Chrome 71. Możesz zacząć go używać jako stopniowe ulepszenie dzisiaj.
Inny interfejs API Animation?
W rzeczywistości nie, to tylko kontynuacja tego, co już mieliśmy, i mamy ku temu dobry powód. Zacznijmy od początku. Jeśli chcesz animować dowolny element DOM w internecie masz dzisiaj do wyboru dwie opcje: przejścia CSS, proste przejścia A do B, animacje CSS potencjalnie cykliczne, bardziej złożone animacje czasowe oraz interfejs Web Animations API. (WAAPI) w przypadku niemal dowolnie złożonych animacji. Tablica pomocy WAAPI wygląda dość ponuro, idzie ku górze. Do tego czasu będzie jeszcze polyfill.
Cechą wspólną wszystkich tych metod jest to, że są bezstanowe na czas. Niektóre efekty, które testują programiści, nie są ani ograniczonych czasowo czy bezstanowych. Na przykład słynny pasek paralaksy to: jak sama nazwa wskazuje, będą przewijane. Zaimplementowanie w internecie skutecznego mechanizmu paralaksy na potrzeby przewijania jest obecnie zaskakująco trudne.
A co z bezstannością? Weźmy na przykład pasek adresu Chrome na Androida, przykład. Jeśli przewiniesz w dół, zniknie on z widoku. Ale gdy przewiniesz palcem w górę, urządzenie powraca, nawet jeśli będziesz w połowie drogi. w dół tej strony. Animacja zależy nie tylko od pozycji przewijania, ale też od poprzedniego kierunku przewijania. Jest stanowa.
Innym problemem jest styl pasków przewijania. Takie tytuły nie są nudne ani stylizowane co najmniej za mało stylu. Co zrobić, jeśli na pasku przewijania chcę wyświetlać kot nyan? Niezależnie od wybranej metody, utworzenie niestandardowego paska przewijania nie wydajny ani prosty.
Trzeba jednak pamiętać, że wszystko to jest niezręczne i trudne do uniemożliwienia.
jego efektywne wdrażanie. Większość z nich bazuje na zdarzeniach lub
requestAnimationFrame
, który może utrzymywać szybkość 60 kl./s, nawet na ekranie
może działać z prędkością 90 kl./s, 120 kl./s lub większą i wykorzystywać
bezcennego budżetu na ramkę wątku głównego.
Worklet animacji rozszerza możliwości internetowego stosu animacji, o takie efekty. Zanim przejdziemy do szczegółów, który zawiera najbardziej aktualne informacje o animacjach.
Podstawowe informacje o animacjach i osi czasu
WAAPI i Worklet animacji szeroko wykorzystują oś czasu, korygować animacje i efekty w wybrany przez siebie sposób. Ta sekcja jest szybkie przypomnienie lub wprowadzenie do osi czasu i sposobu ich współdziałania z animacjami.
Każdy dokument zawiera document.timeline
. Wartość zaczyna się od 0, gdy dokument jest
i odlicza milisekundy od momentu utworzenia dokumentu. Wszystkie z tej listy
Animacje w dokumencie będą działać względem tej osi czasu.
Aby zyskać więcej konkretów, przyjrzyjmy się temu fragmentowi kodu WAAPI.
const animation = new Animation(
new KeyframeEffect(
document.querySelector('#a'),
[
{
transform: 'translateX(0)',
},
{
transform: 'translateX(500px)',
},
{
transform: 'translateY(500px)',
},
],
{
delay: 3000,
duration: 2000,
iterations: 3,
}
),
document.timeline
);
animation.play();
Gdy wywołujemy funkcję animation.play()
, animacja używa parametru currentTime
osi czasu
. Opóźnienie animacji wynosi 3000 ms, co oznacza, że
animacja rozpocznie się (lub stanie się „aktywna”), gdy oś czasu osiągnie wartość „startTime”
- 3000
. After that time, the animation engine will animate the given element from the first keyframe (
translateX(0)), through all intermediate keyframes (
translateX(500px)) all the way to the last keyframe (
translateY(500px)) in exactly 2000ms, as prescribed by the
durationoptions. Since we have a duration of 2000ms, we will reach the middle keyframe when the timeline's
currentTimeis
startTime + 3000 + 1000and the last keyframe at
startTime + 3000 + 2000`. Najważniejsze jest, elementy sterujące osią czasu w animacji.
Gdy animacja dotrze do ostatniej klatki kluczowej, przeskoczy z powrotem do pierwszej
klatki kluczowej i rozpoczynać kolejną iterację animacji. Ten proces powtarza
łącznie 3 razy od ustawienia iterations: 3
. Gdybyśmy chcieli, by animacja była
nigdy nie przestaliby wpisywać znaków iterations: Number.POSITIVE_INFINITY
. Oto
result kodu
powyżej.
WAAPI ma niesamowicie zaawansowane możliwości i jest w nim znacznie więcej funkcji, np. wygładzanie, odsunięcia początkowe, wagi klatek kluczowych i zachowanie wypełnienia, które spowodowałoby tego artykułu. Jeśli chcesz dowiedzieć się więcej, przeczytaj ten artykuł na temat animacji CSS w trikach CSS.
Pisanie Workleta animacji
Skoro znamy już koncepcję osi czasu, możemy zająć się Worklet animacji i sposób jego pomieszania z osiami czasu Animacja Worklet API nie tylko opiera się na WAAPI, ale jest – w kontekście elastycznej sieci – podstawowym elementem niższego poziomu, wyjaśnia, jak działa WAAPI. Jeśli chodzi o składnię, są one bardzo podobne pod względem składni:
Worklet animacji | protokół WAAPI |
---|---|
new WorkletAnimation( 'passthrough', new KeyframeEffect( document.querySelector('#a'), [ { transform: 'translateX(0)' }, { transform: 'translateX(500px)' } ], { duration: 2000, iterations: Number.POSITIVE_INFINITY } ), document.timeline ).play(); |
new Animation( new KeyframeEffect( document.querySelector('#a'), [ { transform: 'translateX(0)' }, { transform: 'translateX(500px)' } ], { duration: 2000, iterations: Number.POSITIVE_INFINITY } ), document.timeline ).play(); |
Różnica dotyczy pierwszego parametru, który jest nazwą workletu. który jest podstawą tej animacji.
Wykrywanie cech
Chrome jest pierwszą przeglądarką, w której ta funkcja jest dostępna, więc musisz zadbać o to,
kod nie oczekuje, że element AnimationWorklet
będzie dostępny. Przed wczytaniem
Worklet, należy wykryć, czy przeglądarka użytkownika obsługuje
AnimationWorklet
z prostą weryfikacją:
if ('animationWorklet' in CSS) {
// AnimationWorklet is supported!
}
Wczytuję Worklet
Worklety to nowa koncepcja wprowadzonej przez grupę zadaniową Houdini. Dzięki niej łatwiej tworzyć i skalować nowe interfejsy API. Omówimy szczegóły dotyczące Workletów trochę później, ale dla uproszczenia mogą być one takie proste wątki (takie jak instancje robocze).
Musimy się upewnić, że wczytaliśmy Worklet o nazwie „passthrough” przed zadeklarowaniem animacji:
// index.html
await CSS.animationWorklet.addModule('passthrough-aw.js');
// ... WorkletAnimation initialization from above ...
// passthrough-aw.js
registerAnimator(
'passthrough',
class {
animate(currentTime, effect) {
effect.localTime = currentTime;
}
}
);
Co się tutaj dzieje? Rejestruujemy zajęcia jako animator za pomocą
Wywołanie registerAnimator()
obiektu AnimationWorklet, które nosi nazwę „passthrough”.
Ta sama nazwa, która została użyta w konstruktorze WorkletAnimation()
powyżej. Gdy funkcja
rejestracja została zakończona, obietnica zwrócona przez firmę addModule()
zostanie rozwiązana i
możemy zacząć tworzyć animacje na jego podstawie.
Metoda animate()
naszej instancji będzie wywoływana dla każdej klatki
przeglądarka chce wyrenderować, przekazując currentTime
osi czasu animacji
oraz efekt, który jest obecnie przetwarzany. Mamy tylko jedną
efektu, KeyframeEffect
i używamy currentTime
do ustawienia efektu
localTime
, dlatego ten animator jest nazywany „przejazdem”. Z tym kodem do
Worklet, WAAPI i AnimationWorklet powyżej działają dokładnie
jak widać w tabeli
demo.
Godzina
Parametr currentTime
metody animate()
to currentTime
parametru
do konstruktora WorkletAnimation()
. W poprzedniej
na przykład przerobiliśmy ten czas. Ponieważ jednak jest to
w kodzie JavaScript i możemy zniekształcić czas 💫
function remap(minIn, maxIn, minOut, maxOut, v) {
return ((v - minIn) / (maxIn - minIn)) * (maxOut - minOut) + minOut;
}
registerAnimator(
'sin',
class {
animate(currentTime, effect) {
effect.localTime = remap(
-1,
1,
0,
2000,
Math.sin((currentTime * 2 * Math.PI) / 2000)
);
}
}
);
Wykorzystujemy Math.sin()
(currentTime
) i przypisujemy tę wartość do
zakres [0; 2000], czyli zakres czasu, dla którego zdefiniowany jest nasz efekt. Teraz
wyglądają zupełnie inaczej –
zmieniły klatki kluczowe lub opcje animacji. Kodem Workletu można
dowolnego złożonego charakteru i umożliwia automatyczne definiowanie efektów,
w jakiej kolejności i w jakim zakresie.
Opcje nad opcjami
Możesz ponownie użyć Worklet i zmienić jego numery. Z tego powodu Konstruktor WorkletAnimation umożliwia przekazanie obiektu options do Workletu:
registerAnimator(
'factor',
class {
constructor(options = {}) {
this.factor = options.factor || 1;
}
animate(currentTime, effect) {
effect.localTime = currentTime * this.factor;
}
}
);
new WorkletAnimation(
'factor',
new KeyframeEffect(
document.querySelector('#b'),
[
/* ... same keyframes as before ... */
],
{
duration: 2000,
iterations: Number.POSITIVE_INFINITY,
}
),
document.timeline,
{factor: 0.5}
).play();
W tym przykładzie Obie animacje są oparte na tym samym kodzie, ale z różnymi opcjami.
Podaj swój region.
Jak już wspomniałem, jednym z kluczowych problemów, które ma rozwiązać zadanie animacji, jest
w postaci animacji stanowych. Worklety animacji mogą przechowywać stan. Jednak jedna z nich
z głównych funkcji Workletów jest to, że można je przenosić do innych
a nawet zniszczyć ją w celu zapisania zasobów, co mogłoby także zniszczyć
stanu. Aby zapobiec utracie stanu, Worklet animacji oferuje punkt zaczepienia, który
jest wywoływany przed zniszczeniem listy zadań, której można użyć do zwrócenia stanu.
obiektu. Ten obiekt zostanie przekazany do konstruktora, gdy Worklet zostanie
na nowo. Przy pierwszym tworzeniu ten parametr będzie miał wartość undefined
.
registerAnimator(
'randomspin',
class {
constructor(options = {}, state = {}) {
this.direction = state.direction || (Math.random() > 0.5 ? 1 : -1);
}
animate(currentTime, effect) {
// Some math to make sure that `localTime` is always > 0.
effect.localTime = 2000 + this.direction * (currentTime % 2000);
}
destroy() {
return {
direction: this.direction,
};
}
}
);
Za każdym razem, gdy odświeżysz tę demonstrację, otrzymasz 50/50
prawdopodobieństwo, w którym kierunku obróci się kwadrat. Gdyby przeglądarka została demontowana
i przenieść go do innego wątku,
Math.random()
wywołuje proces tworzenia, co może spowodować nagłą zmianę
kierunek. Aby tego uniknąć, zwracamy animacje
losowo wybrany kierunek jako state (stan) i użyj go w konstruktorze, jeśli jest podany.
Zagłębianie się w kontynuum czasoprzestrzenne: ScrollTimeline
Jak widać w poprzedniej sekcji, AnimationWorklet pozwala
automatycznie określić wpływ zmian w harmonogramie na wyniki,
animację. Jednak do tej pory zawsze znajdowała się tu oś czasu document.timeline
, czyli
śledzi czas.
ScrollTimeline
otwiera przed Tobą nowe możliwości i umożliwia tworzenie animacji
z przewijaniem zamiast z czasem. Wykorzystujemy pierwszy
„przekazywanie” Worklet dla tego
demonstracja:
new WorkletAnimation(
'passthrough',
new KeyframeEffect(
document.querySelector('#a'),
[
{
transform: 'translateX(0)',
},
{
transform: 'translateX(500px)',
},
],
{
duration: 2000,
fill: 'both',
}
),
new ScrollTimeline({
scrollSource: document.querySelector('main'),
orientation: 'vertical', // "horizontal" or "vertical".
timeRange: 2000,
})
).play();
Zamiast wartości document.timeline
tworzymy nowy ScrollTimeline
.
Być może zgadniesz. ScrollTimeline
nie używa czasu, ale
Pozycja przewijania scrollSource
do ustawienia currentTime
w Worklet. Bycie
przewinięto do końca na górę (lub w lewo) oznacza currentTime = 0
, a
przewinięcie do końca na sam dół (lub w prawo) powoduje ustawienie wartości currentTime
na
timeRange
Jeśli przewiniesz pole w tej
demo.
kontrolować położenie czerwonego pola.
Jeśli utworzysz ScrollTimeline
z elementem, który nie przewija się, funkcja
currentTime
na osi czasu będzie NaN
. Zwłaszcza przy elastycznym projektowaniu
przygotuj się na NaN
swojego currentTime
. Często
sensowne jest domyślne ustawienie wartości 0.
Od dawna szukaliśmy możliwości łączenia animacji z pozycją przewijania, ale nigdy nie udało się jej osiągnąć na takim poziomie wierności (oprócz sposoby obejścia w kodzie CSS3D). Worklet animacji umożliwia stosowanie tych efektów zostały wdrożone w prosty sposób przy zachowaniu dużej wydajności. Na przykład: efekt przewijania z efektem paralaksy, demo pokazuje, Teraz wystarczy kilka wierszy, aby utworzyć animację przewijaną.
Dla zaawansowanych
Worklety
Worklety to konteksty JavaScriptu z osobnym zakresem i bardzo małym interfejsem API na różnych powierzchniach. Mała powierzchnia interfejsu API umożliwia bardziej agresywną optymalizację zwłaszcza na niedrogich urządzeniach. Dodatkowo Worklety nie są powiązane z w określonym cyklu zdarzeń, ale w razie potrzeby można przechodzić między wątkami. To jest szczególnie ważne w przypadku obiektu AnimationWorklet.
Nsynchronizacja kompozytora
Niektóre właściwości CSS szybko się animują, Nie. Niektóre właściwości wymagają do działania GPU, przeglądarka ponownie wyświetli cały dokument.
W Chrome (podobnie jak w wielu innych przeglądarkach) mamy proces nazywany kompozytorem, czyją to zadanie – i bardzo upraszczam – rozmieszczanie warstw tekstury, a następnie możliwie regularnie aktualizować ekran za pomocą GPU. najlepiej z szybkością, od której aktualizuje się ekran (zwykle 60 Hz). W zależności od tego, Właściwości CSS są animowane, przeglądarka może wymagać jedynie polecenia kompozytora wykonuje swoją pracę, natomiast inne właściwości muszą uruchamiać układ, który jest którą może wykonać tylko wątek główny. W zależności od tego, jakie usługi Jeśli plan ma być animowany, Worklet animacji zostanie powiązany z głównym elementem lub uruchomić w osobnym wątku zsynchronizowanym z kompozytorem.
Klepnięcie w nadgarstku
Zwykle istnieje tylko jeden proces kompozytora, który może być współużytkowany wiele kart, ponieważ GPU jest bardzo wymagającym zasobem. Jeśli kompozytor otrzyma w jakiś sposób są zablokowane, cała przeglądarka zawiesza się i nie reaguje na danych wejściowych użytkownika. Należy tego unikać za wszelką cenę. Co się więc dzieje, gdy Worklet nie może dostarczyć danych, których kompozytor potrzebuje w czasie do zatrzymania klatki wyrenderowano?
W takim przypadku Worklet może się „prześlizgać” (zgodnie ze specyfikacją). Jest odwrotna kompozytora, który może ponownie użyć danych ostatniej klatki do utrzymuj liczbę klatek na sekundę. Wizualnie wygląda to trochę twardo, ale duży różnica polega na tym, że przeglądarka wciąż reaguje na dane wejściowe użytkownika.
Podsumowanie
AnimationWorklet ma wiele aspektów i korzyści, jakie oferuje w internecie. Oczywistymi korzyściami jest większa kontrola nad animacjami i nowe sposoby animacje, które zapewniają nowy poziom jakości wizualnej w internecie. Interfejsy API jest również bardziej odporna na zacinanie, a jednocześnie dostęp do wszystkich nowych funkcji jednocześnie.
Worklet animacji jest w wersji Canary. Naszym celem jest uruchomienie wersji próbnej Chrome 71. Z niecierpliwością czekamy na Wasze nowe doświadczenia w internecie i usłyszenia o tym, co możemy poprawić. Dostępna jest też kod polyfill , który obejmuje ten sam interfejs API, ale nie obejmuje izolacji wydajności.
Pamiętaj, że przejścia CSS i animacje CSS są nadal prawidłowe i może być znacznie prostsza w przypadku podstawowych animacji. Jeśli jednak chcesz Możesz utworzyć aplikację AnimationWorklet.