W kierunku wskaźnika płynności animacji

Dowiedz się więcej o mierzeniu animacji, kadrowaniu animacji i ogólnej płynności strony.

Behdad Bakhshinategh
Behdad Bakhshinategh
Jonathan Ross
Jonathan Ross
Michal Mocny
Michal Mocny

Prawdopodobnie zdarzyło Ci się, że strony „zacinały się” lub „zawieszały” podczas przewijania lub animacji. Te funkcje nie są płynne. Aby rozwiązać tego typu problemy, zespół Chrome pracował nad dodaniem większego wsparcia dla narzędzi laboratoryjnych do wykrywania animacji, a także nad ulepszaniem diagnostyki ścieżki renderowania w Chromium.

Chcielibyśmy podzielić się z Tobą informacjami o ostatnich postępach, przedstawić konkretne wskazówki dotyczące narzędzi i przedstawić pomysły na przyszłe wskaźniki płynności animacji. Jak zawsze chętnie poznamy Twoją opinię.

W tym poście omówimy 3 główne tematy:

  • Szybki przegląd animacji i klatek animacji.
  • Nasze obecne przemyślenia na temat pomiaru ogólnej płynności animacji.
  • Kilka praktycznych sugestii dotyczących wykorzystania narzędzi laboratoryjnych.

Co to są animacje?

Animacje ożywiają treści. Dzięki animacjom treści mogą się poruszać, zwłaszcza w reakcji na interakcje użytkowników, co sprawia, że korzystanie z aplikacji jest bardziej naturalne, zrozumiałe i przyjemne.

Źle zaimplementowane animacje lub zbyt duża ich liczba mogą jednak pogorszyć wrażenia użytkownika i uczynić je nieprzyjemnymi. Wszyscy pewnie korzystaliśmy z interfejsu, do którego dodano zbyt wiele „użytecznych” efektów przejścia, które w rzeczywistości stają się nieprzyjazne, gdy działają nieprawidłowo. Niektórzy użytkownicy mogą preferować ograniczoną animację, a Ty powinieneś uwzględniać ich preferencje.

Jak działają animacje?

Przypominamy, że przetwarzanie odbywa się w ramach łańcucha przetwarzania, który składa się z kilku kolejnych etapów:

  1. Style: obliczanie stylów zastosowanych do elementów.
  2. Układ: wygeneruj geometrię i położenie każdego elementu.
  3. Paint:wypełnij piksele każdego elementu warstwami.
  4. Kompozycja: rysowanie warstw na ekranie.

Animacje można definiować na wiele sposobów, ale wszystkie one działają w ten sam sposób:

  • Dostosowywanie właściwości układu.
  • Dostosowywanie właściwości paint.
  • Dostosowywanie właściwości kompozycji.

Ponieważ te etapy są uporządkowane chronologicznie, ważne jest, aby animacje definiować w oparciu o właściwości, które znajdują się dalej w łańcuchu przetwarzania. Im wcześniej nastąpiła aktualizacja, tym większe są koszty i tym mniejsze jest prawdopodobieństwo, że przebiegnie ona bez zakłóceń. (więcej informacji znajdziesz w sekcji Wydajność renderowania).

Animacja właściwości układu może być wygodna, ale wiąże się z pewnymi kosztami, nawet jeśli nie są one od razu widoczne. W miarę możliwości animacje powinny być definiowane w sposób uwzględniający zmiany właściwości złożonych.

Aby zapewnić płynne i wydajne animacje, warto zacząć od deklaratywnych animacji CSS lub korzystania z animacji internetowych oraz animowania właściwości złożonych. Nie gwarantuje to jednak płynności, ponieważ nawet wydajne animacje internetowe mają ograniczenia wydajności. Dlatego zawsze warto mierzyć skuteczność.

Czym są klatki animacji?

Zmiany wizualne strony mogą się pojawić dopiero po pewnym czasie. Zmiana wizualna spowoduje utworzenie nowej klatki animacji, która ostatecznie zostanie wyrenderowana na ekranie użytkownika.

Wyświetla aktualizacje w określonych odstępach czasu, dzięki czemu aktualizacje wizualne są grupowane. Wiele wyświetlaczy aktualizuje się w określonym odstępie czasu, np. 60 razy na sekundę (czyli 60 Hz). Niektóre nowocześniejsze wyświetlacze mogą oferować wyższą częstotliwość odświeżania (90–120 Hz staje się coraz bardziej powszechne). Często takie wyświetlacze mogą aktywnie dostosowywać częstotliwość odświeżania do potrzeb lub nawet oferować zmienną częstotliwość odświeżania.

Celem każdej aplikacji, np. gry lub przeglądarki, jest przetworzenie wszystkich zbiorczych aktualizacji wizualnych i utworzenie kompletnego klatki animacji, która będzie wizualnie poprawna, zawsze w określonym czasie. Pamiętaj, że ten cel jest zupełnie inny od innych ważnych zadań przeglądarki, takich jak szybkie wczytywanie treści z sieci czy wydajne wykonywanie zadań JavaScript.

W pewnym momencie może okazać się zbyt trudne, aby w określonym terminie wprowadzić wszystkie zmiany wizualne. W takim przypadku przeglądarka wyrzuca ramkę. Ekran nie wraca do czerni, tylko się powtarza. Widzisz tę samą aktualizację wizualną przez dłuższy czas – tę samą klatkę animacji, która została wyświetlona w poprzedniej klatce.

To się często zdarza. Nie musi być ona nawet zauważalna, zwłaszcza w przypadku treści statycznych lub podobnych do dokumentów, które są powszechne na platformach internetowych. Utrata klatek staje się widoczna tylko wtedy, gdy występują ważne zmiany wizualne, takie jak animacje, które wymagają ciągłego przesyłania aktualizacji animacji w celu zapewnienia płynnego ruchu.

Co wpływa na klatki animacji?

Deweloperzy internetowi mogą mieć duży wpływ na to, jak szybko i efektywnie przeglądarka będzie mogła renderować oraz prezentować zmiany wizualne.

Oto kilka przykładów:

  • Używanie treści, które są zbyt duże lub wymagają zbyt wielu zasobów, aby można je było szybko zdekodować na urządzeniu docelowym.
  • Używanie zbyt wielu warstw, które wymagają zbyt dużej ilości pamięci GPU.
  • definiowanie zbyt złożonych stylów CSS lub animacji internetowych;
  • Używanie nieprawidłowych wzorców projektowania, które wyłączają optymalizacje szybkiego renderowania.
  • zbyt dużo pracy JS w wątku głównym, co prowadzi do długich zadań blokujących aktualizacje wizualne;

Ale jak możesz wiedzieć, kiedy klatka animacji nie zmieściła się w terminie i spowodowała pominięcie klatki?

Jedną z możliwych metod jest stosowanie requestAnimationFrame()ankiety, ale ma ona kilka wad. requestAnimationFrame(), czyli „rAF”, informuje przeglądarkę, że chcesz wykonać animację, i prosi o możliwość wykonania tego przed kolejnym etapem renderowania w pipeline. Jeśli funkcja wywołania zwrotnego nie zostanie wywołana w oczekiwanym momencie, oznacza to, że nie została wykonana funkcja paint, a co najmniej jeden lub więcej klatek zostało pominięte. Dzięki sprawdzaniu i liczeniu, jak często wywoływana jest funkcja RAF, możesz obliczyć „liczba klatek na sekundę” (FPS).

let frameTimes = [];
function pollFramesPerSecond(now) {
  frameTimes = [...frameTimes.filter(t => t > now - 1000), now];
  requestAnimationFrame(pollFramesPerSecond);
  console.log('Frames per second:', frameTimes.length);
}
requestAnimationFrame(pollFramesPerSecond);

Korzystanie z requestAnimationFrame() nie jest dobrym pomysłem z kilku powodów:

  • Każdy skrypt musi mieć własną pętlę sprawdzania.
  • Może to zablokować ścieżkę krytyczna.
  • Nawet jeśli polling rAF jest szybki, może uniemożliwić requestIdleCallback() planowanie długich bloków bezczynności podczas ciągłego używania (bloków, które przekraczają 1 klatka).
  • Podobnie brak długich bloków bezczynności uniemożliwia przeglądarce zaplanowanie innych długotrwałych zadań (takich jak dłuższe zbieranie elementów do usunięcia i inne zadania w tle lub spekulacyjne).
  • Jeśli polling jest włączony i wyłączony, nie zauważysz przypadków przekroczenia budżetu ramki.
  • W przypadku, gdy przeglądarka używa zmiennej częstotliwości aktualizacji (np. ze względu na stan zasilania lub widoczność), wywoływanie metody poll spowoduje fałszywie pozytywne wyniki.
  • Co najważniejsze, nie obejmuje ona wszystkich typów aktualizacji animacji.

Zbyt duża ilość pracy w wątku głównym może wpływać na możliwość wyświetlania klatek animacji. Sprawdź przykład Jank, aby zobaczyć, jak animacja obsługiwana przez rAF, gdy wątek główny ma zbyt dużo pracy (np. układ), powoduje utratę klatek, mniejszą liczbę wywołań zwrotnych rAF i niższą liczbę klatek na sekundę.

Gdy wątek główny zacznie się zacinać, aktualizacje wizualne zaczną się zacinać. To nie działa.

Wiele narzędzi do pomiarów koncentrowało się głównie na tym, aby główny wątek mógł w swoim czasie zwracać wartości, a ramki animacji działały płynnie. To jednak nie wszystko. Na przykład:

Film powyżej pokazuje stronę, która okresowo wstrzykuje długie zadania do głównego wątku. Te długie zadania całkowicie uniemożliwiają stronie wyświetlanie niektórych typów aktualizacji wizualnych. W lewym górnym rogu można zauważyć odpowiadający spadek requestAnimationFrame() zgłaszanych FPS do 0.

Mimo tak długich zadań strona nadal płynnie się przewija. Wynika to z faktu, że w nowoczesnych przeglądarkach przewijanie jest często wielowątkowe i w pełni zarządzane przez kompozytor.

Ten przykład zawiera jednocześnie wiele utraconych klatek na głównym wątku, ale nadal ma wiele prawidłowo przesłanych klatek przewijania na wątku kompozytora. Po zakończeniu długiego zadania aktualizacja głównego wątku nie powoduje żadnych zmian wizualnych. Ankieta z użyciem interfejsu raf sugeruje spadek liczby klatek do 0, ale wizualnie użytkownik nie zauważy różnicy.

W przypadku klatek animacji sprawa nie jest tak prosta.

Klatki animacji: ważne aktualizacje

Powyższy przykład pokazuje, że requestAnimationFrame() to nie wszystko.

Kiedy aktualizacje animacji i klatki animacji mają znaczenie? Oto niektóre kryteria, które rozważamy i na temat których chcielibyśmy uzyskać opinię:

  • Aktualizacje wątku głównego i kompozytora
  • Brakujące aktualizacje farb
  • Wykrywanie animacji
  • Jakość a ilość

Aktualizacje wątku głównego i kompozytora

Aktualizacje klatek animacji nie są typu logicznego. Nie oznacza to, że klatki mogą być tylko całkowicie usunięte lub całkowicie wyświetlane. Istnieje wiele powodów, dla których kadr animacji może być częściowo wyświetlany. Innymi słowy, może ona zawierać jednocześnie niektóre nieaktualne treści oraz nowe elementy wizualne.

Najczęstszym przykładem jest sytuacja, w której przeglądarka nie może przeprowadzić nowej aktualizacji głównego wątku w ramach limitu czasu kadru, ale ma nową aktualizację wątku kompozytora (np. w przykładzie przewijania w wątkach z poprzedniego akapitu).

Jednym z ważnych powodów, dla których zalecamy używanie deklaratywnych animacji do animowania właściwości złożonych, jest to, że umożliwia to sterowanie animacją wyłącznie przez wątek kompozytora, nawet gdy wątek główny jest zajęty. Te typy animacji mogą nadal efektywnie i równolegle generować aktualizacje wizualne.

Z drugiej strony, może się zdarzyć, że aktualizacja głównego wątku stanie się dostępna do wyświetlenia dopiero po przekroczeniu kilku terminów dotyczących ramki. W tym przypadku przeglądarka będzie mieć jakiś nowy update, ale nie będzie to najnowsza wersja.

Ogólnie mówiąc, ramki, które zawierają niektóre nowe elementy wizualne, ale nie wszystkie, uznajemy za częściowe ramki. Częściowe klatki są dość powszechne. W idealnej sytuacji aktualizacje częściowe obejmowałyby co najmniej najważniejsze aktualizacje wizualne, takie jak animacje, ale może się to zdarzyć tylko wtedy, gdy animacje są obsługiwane przez wątek kompozytora.

Brakujące aktualizacje farb

Innym rodzajem aktualizacji częściowej jest sytuacja, gdy media, takie jak obrazy, nie zostały jeszcze zdekodowane i rasteryzowane na czas wyświetlania klatki.

Nawet jeśli strona jest całkowicie statyczna, przeglądarki mogą nie nadążać z renderowaniem zmian wizualnych podczas szybkiego przewijania. Dzieje się tak, ponieważ piksele treści poza widocznym obszarem widoku mogą zostać odrzucone, aby zaoszczędzić pamięć GPU. Renderowanie pikseli wymaga czasu, a renderowanie wszystkich elementów po przewinięciu dużej ilości danych, np. po przesunięciu palcem, może zająć więcej czasu niż renderowanie pojedynczego klatki. Jest to tak zwane przeplatanie.

W przypadku każdej okazji do renderowania klatki można śledzić, ile z najnowszych aktualizacji wizualnych rzeczywiście pojawiło się na ekranie. Pomiar możliwości wykonywania tej czynności w przypadku wielu klatek (lub w ciągu określonego czasu) jest powszechnie znany jako przepustowość klatek.

Jeśli procesor graficzny jest naprawdę przeciążony, przeglądarka (lub platforma) może ograniczyć częstotliwość prób aktualizacji wizualnych, co spowoduje zmniejszenie skutecznych częstotliwości klatek. Chociaż technicznie może to zmniejszyć liczbę utraconych aktualizacji klatek, wizualnie nadal będzie to wyglądać jak niższa przepustowość klatek.

Nie wszystkie typy niskiej przepustowości klatek są jednak złe. Jeśli strona jest w większości nieaktywna i nie ma aktywnych animacji, niska liczba klatek na sekundę jest tak samo atrakcyjna wizualnie jak wysoka liczba klatek na sekundę (a może też oszczędzać baterię).

Kiedy przepustowość klatek ma znaczenie?

Wykrywanie animacji

Wysoka przepustowość klatek ma znaczenie zwłaszcza w okresach ważnych animacji. Różne typy animacji zależą od wizualnych aktualizacji z konkretnego wątku (głównego, kompozytora lub wątku roboczego), więc ich aktualizacja zależy od tego, czy dany wątek zdąży je przekazać w określonym terminie. Mówimy, że dany wątek wpływa na płynność, gdy jest aktywna animacja, która zależy od aktualizacji tego wątku.

Niektóre typy animacji są łatwiejsze do zdefiniowania i wykrycia niż inne. Deklaratywna animacja lub animacja sterowana przez użytkownika jest łatwiejsza do zdefiniowania niż animacja sterowana przez JavaScript, która jest implementowana jako okresowe aktualizacje właściwości stylów do animowania.

Nawet w przypadku requestAnimationFrame() nie zawsze można zakładać, że każde wywołanie rAF powoduje aktualizację wizualną lub animację. Na przykład użycie pollingu rAF tylko do śledzenia częstotliwości wyświetlania klatek (jak pokazano powyżej) nie powinno wpływać na pomiary płynności, ponieważ nie ma wtedy żadnej aktualizacji wizualnej.

Jakość a ilość

Wykrywanie animacji i aktualizacji klatek animacji to tylko część historii, ponieważ uwzględnia tylko liczbę aktualizacji animacji, a nie ich jakość.

Podczas oglądania filmu możesz na przykład zobaczyć płynną liczbę klatek na sekundę wynoszącą 60. Technicznie jest to płynne, ale sam film może mieć niski bitrate lub problemy z buforowaniem w sieci. Dane te nie są rejestrowane bezpośrednio przez wskaźniki płynności animacji, ale mogą być irytujące dla użytkownika.

Zdarza się też, że gra, która korzysta z <canvas> (np. z technik takich jak płótno poza ekranem, aby zapewnić płynną animację), może technicznie wyświetlać płynne klatki animacji, ale nie wczytywać do sceny zasobów o wysokiej jakości lub generować artefaktów podczas renderowania.

Oczywiście w witrynie mogą też występować źle animowane elementy.

GIF z przedszkola w trakcie budowy

Chyba były całkiem fajne jak na swoje czasy.

Stany pojedynczej klatki animacji

Ponieważ klatki mogą być wyświetlane częściowo lub mogą być pomijane w sposób, który nie wpływa na płynność, zaczęliśmy traktować każdą klatkę jako całość lub płynność.

Oto zakres sposobów, w jaki interpretujemy stan pojedynczego klatki animacji, w kolejności od najlepszego do najgorszego:

Nie potrzebuję aktualizacji Czas bezczynności, powtórzenie poprzedniej klatki.
Pełna prezentacja Aktualizacja wątku głównego została zatwierdzona w terminie lub nie była potrzebna.
Częściowo zaprezentowana Tylko kompozytor; opóźniona aktualizacja głównego wątku nie wprowadziła żadnych zmian wizualnych.
Częściowo zaprezentowana Tylko kompozytor: wątek główny został zaktualizowany wizualnie, ale ta aktualizacja nie zawierała animacji, która wpływa na płynność.
Częściowo zaprezentowana Tylko kompozytor: wątek główny zawierał aktualizację wizualną, która wpływa na płynność, ale zamiast tego został użyty nieaktualny obraz.
Częściowo zaprezentowana Tylko kompozytor; bez pożądanej głównej aktualizacji, a aktualizacja kompozytora ma animację, która wpływa na płynność.
Częściowo zaprezentowana Tylko kompozytor, ale aktualizacja kompozytora nie zawiera animacji, która wpływa na płynność.
Pominięta klatka Brak aktualizacji. Nie była potrzebna żadna aktualizacja kompozytora, a główna została opóźniona.
Pominięta klatka Pożądana była aktualizacja kompozytora, ale została opóźniona.
Nieaktualna klatka Pożądana aktualizacja została wygenerowana przez renderer, ale GPU nie wyświetlił jej przed terminem synchronizacji pionowej.

Można je przekształcić w swego rodzaju wynik. Można go interpretować jako prawdopodobieństwo, że użytkownik go zauważy. Pojedyncze utracone klatki mogą nie być bardzo widoczne, ale sekwencja wielu utraconych klatek, które wpływają na płynność, na pewno jest.

Podsumowanie: wskaźnik odsetek utraconej liczby klatek

Czasami konieczne jest dokładne sprawdzenie stanu każdego klatki animacji, ale przydatne jest też przypisanie szybkiego wyniku „na pierwszy rzut oka” dla danego doświadczenia.

Ponieważ klatki mogą być częściowo wyświetlane, a nawet całkowicie pominięte aktualizacje klatek mogą nie wpływać na płynność, chcemy skupić się nie tylko na zliczaniu klatek, ale też na sprawiedliwym zakresie, w jakim przeglądarka nie może zapewnić pełnych wizualnie aktualizacji w ważnych momentach.

Model mentalny powinien przejść od:

  1. Liczba klatek na sekundę to
  2. wykrywanie brakujących i ważnych aktualizacji animacji, aby
  3. Odsetek odrzuconych w określonym okresie.

Liczy się proporcja czasu oczekiwania na ważne aktualizacje. Uważamy, że jest to zgodne z naturalnym sposobem, w jaki użytkownicy doświadczają płynności treści internetowych w praktyce. Do tej pory jako początkowy zestaw danych używaliśmy tych danych:

  • Średni odsetek opuszczonych klatek: dotyczy wszystkich klatek animacji, które nie są w stanie bezczynności w całości osi czasu.
  • Najgorszy przypadek odsetka utraconej liczby klatek: mierzony w przesuwających się oknach czasowych o długości 1 sekundy.
  • 95 percentyl liczby utraconych klatek: mierzony w oknach czasowych o długości 1 sekunda.

Obecnie można je znaleźć w niektórych narzędziach deweloperskich w Chrome. Te dane dotyczą tylko ogólnego przepływu danych, ale bierzemy pod uwagę też inne czynniki, takie jak opóźnienie klatek.

Wypróbuj to w narzędziach dla deweloperów.

Wyświetlacz HUD

Chromium ma ukryty za flagą (chrome://flags/#show-performance-metrics-hud) skrót Performance HUD, w którym znajdziesz na żywo wyniki dotyczące m.in. podstawowych wskaźników internetowych oraz kilka eksperymentalnych definicji płynności animacji na podstawie odsetek utracone ramki na przestrzeni czasu.

Wyświetlacz HUD

Statystyki renderowania klatek

Włącz „Statystyki renderowania klatek” w DevTools, aby zobaczyć na żywo nowe klatki animacji, które są oznaczone kolorami w celu odróżnienia częściowych od pełnych aktualizacji. Podawana liczba klatek na sekundę dotyczy tylko w pełni wyświetlonych klatek.

Statystyki renderowania klatek

Podgląd klatek w nagraniach profilu wydajności w Narzędziach deweloperskich

Panel wydajności w Narzędziach deweloperskich zawiera od dawna przeglądarkę klatek. Jednak nieco odbiegał od tego, jak działa nowoczesny rdzeń do renderowania. Ostatnio wprowadziliśmy wiele ulepszeń, które są dostępne nawet w najnowszej wersji Chrome Canary. Uważamy, że znacznie ułatwią one debugowanie problemów z animowaniem.

Obecnie zobaczysz, że klatki w przeglądarce klatek są lepiej dopasowane do granic synchronizacji pionowej i oznaczone kolorami na podstawie stanu. Całkowita wizualizacja nie obejmuje jeszcze wszystkich opisanych powyżej niuansów, ale w najbliższej przyszłości planujemy dodać więcej funkcji.

Wyświetlacz ramki w narzędziach deweloperskich w Chrome

Śledzenie w Chrome

Na koniec warto wspomnieć o Chrome Tracing, czyli narzędziu, które pozwala zagłębić się w szczegóły. Za jego pomocą możesz rejestrować ślad „Renderowanie treści internetowych” za pomocą nowego interfejsu Perfetto (lub about:tracing) i dokładnie analizować ścieżkę przetwarzania grafiki w Chrome. Może to być trudne zadanie, ale w niedawno dodanych do Chromium funkcjach znajdziesz kilka ułatwień. Informacje o dostępnych opcjach znajdziesz w dokumentie Cykl życia ramki.

Dzięki zdarzeniom z wykresu możesz jednoznacznie określić:

  • które animacje są odtwarzane (za pomocą zdarzeń o nazwie TrackerValidation);
  • Pobieranie dokładnej osi czasu klatek animacji (za pomocą zdarzeń o nazwie PipelineReporter).
  • W przypadku płynnych animacji aktualizacji dowiedz się, co dokładnie uniemożliwia szybsze działanie animacji (za pomocą podsumowań zdarzeń w ramach zdarzeń PipelineReporter).
  • W przypadku animacji sterowanych danymi wejściowymi sprawdź, ile czasu zajmuje aktualizacja wizualna (za pomocą zdarzeń o nazwie EventLatency).

Raportowanie śledzenia Chrome

Co dalej?

Inicjatywa wskaźników internetowych ma na celu zapewnienie danych i wskazówek dotyczących tworzenia wrażeń w internecie. Dane laboratoryjne, takie jak Total Blocking Time (TBT), są niezbędne do wykrywania i diagnozowania potencjalnych problemów z interakcją. Planujemy zaprojektować podobne dane laboratoryjne dotyczące płynności animacji.

Będziemy Cię informować o naszych postępach w pracy nad pomysłami na opracowanie kompleksowych danych na podstawie informacji o poszczególnych klatkach animacji.

W przyszłości chcielibyśmy też opracować interfejsy API, które umożliwią skuteczne pomiary płynności animacji w przypadku prawdziwych użytkowników w warunkach rzeczywistych, a także w laboratorium. Bądź na bieżąco z informacjami na ten temat.

Prześlij opinię

Cieszymy się z ostatnich ulepszeń i narzędzi dla deweloperów w Chrome, które umożliwiają pomiar płynności animacji. Wypróbuj te narzędzia, porównaj swoje animacje i daj nam znać, do czego doprowadziły te działania.

Komentarze możesz wysyłać do grupy Google web-vitals-feedback, wpisując w polu „Temat” „[Dane dotyczące płynności]”. Czekamy na Twoją opinię.