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. Chcemy powiedzieć, że nie są one łatwe. 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ę.

Omówimy w nim 3 główne tematy:

  • Krótkie spojrzenie na animacje i klatki 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ą zawartość Animacje, które powodują ruch treści, zwłaszcza w reakcji na interakcje użytkowników, mogą sprawić, że korzystanie z aplikacji będzie 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?

Potok renderowania składa się z kilku sekwencyjnych 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.

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

  • Dostosowywanie właściwości układu.
  • Dostosowywanie właściwości paintu.
  • 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 aktualizacja, tym większe są koszty i tym mniej prawdopodobne jest, że proces będzie płynny. (więcej informacji znajdziesz w sekcji Wydajność renderowania).

Animacja właściwości układu jest wygodny, ale wiąże się to 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 po pewnym czasie, więc 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 nowoczesne wyświetlacze mogą mieć wyższe częstotliwości odświeżania (często 90–120 Hz). Wyświetlacze te mogą często w razie potrzeby regulować częstotliwość odświeżania, a nawet oferować w pełni zmienne liczby klatek.

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 klatkę. 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 zawsze jest to w ogóle zauważalne, zwłaszcza w przypadku zawartości statycznej lub dokumentu, co jest rozpowszechnione zwłaszcza na platformie internetowej. 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, aby zapewnić płynne wyświetlanie 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:

  • Nie używaj treści, które są zbyt duże lub wymagają dużo zasobów, aby można je było szybko zdekodować na urządzeniu docelowym.
  • Używanie zbyt wielu warstw wymagających zbyt dużej ilości pamięci GPU.
  • definiowanie zbyt złożonych stylów CSS lub animacji internetowych;
  • Użycie antywzorców projektowych, które wyłączają optymalizacje szybkiego renderowania.
  • Zbyt dużo pracy związanej z JS w wątku głównym, co prowadzi do długich zadań, które blokują 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 czasie, 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 planowanie innych długotrwałych zadań (takich jak dłuższe usuwanie elementów z pamięci podręcznej i inne zadania w tle lub spekulatywne).
  • 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 dodatnie wyniki.
  • Co najważniejsze, nie rejestruje wszystkich zmian animacji.

Zbyt dużo pracy w wątku głównym może wpłynąć 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 jest śmieszne.

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 obniżają możliwość wyświetlania niektórych rodzajów aktualizacji wizualnych. W lewym górnym rogu strony widać spadek tej liczby o requestAnimationFrame() do 0.

Mimo tak długich zadań strona nadal płynnie się przewija. Dzieje się tak, ponieważ w nowoczesnych przeglądarkach przewijanie jest często podzielone na wątki, wyłącznie na podstawie komponentu kompozytora.

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.

Jeśli chodzi o klatki w animacji, historia nie jest taka 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. Oznacza to, że może on zawierać nieaktualne treści i nowe aktualizacje wizualne.

Najczęstszym przykładem jest sytuacja, w której przeglądarka nie może wygenerować nowej aktualizacji wątku głównego w określonym terminie, ale ma nową aktualizację wątku kompozytora (taką jak w poprzednim przykładzie przewijania w wątkach).

Jednym z ważnych powodów korzystania z animacji deklaratywnych do animowania właściwości złożonych jest to, że pozwala to w całości obsługiwać animację 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 uaktualnienia wizualne, ale nie wszystkie, uznajemy za częściowe ramki. Częściowe klatki są dość typowe. W idealnej sytuacji aktualizacje częściowe obejmowałyby co najmniej najważniejsze aktualizacje wizualne, takie jak animacje. Może się to jednak 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ż w celu oszczędzania pamięci GPU można odrzucić renderowanie pikseli treści znajdujących się poza widocznym obszarem. Renderowanie pikseli wymaga czasu, a renderowanie wszystkich elementów po przewinięciu dużej ilości danych, np. przesunięciu palcem, może zająć więcej niż 1 klatka. Jest to powszechnie nazywane szachowaniem.

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 spadek skutecznych częstotliwości klatek. Chociaż technicznie może to zmniejszyć liczbę pominiętych 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

Duża przepustowość klatek ma znaczenie zwłaszcza w okresach z ważnymi animacjami. Różne typy animacji zależą od aktualizacji wizualnych z konkretnego wątku (głównego, kompozytora lub instancji roboczej), więc ich aktualizacja wizualna zależy od wątku, który dostarczył aktualizację w wyznaczonym 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 rodzaje animacji łatwiej zdefiniować i wykryć w porównaniu do innych. 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żywanie odpytywania RAF tylko do śledzenia liczby klatek (jak pokazano powyżej) nie powinno samo w sobie wpływać na pomiary płynności, ponieważ nie wymaga aktualizacji wizualnych.

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. Nie jest to bezpośrednio ujęte przez wskaźniki płynności animacji, ale może i tak zdenerwować użytkownika.

Zdarza się też, że gra, która korzysta z <canvas> (np. z technik pozaekranowego wyświetlania, 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 związanych z renderowaniem.

Oczywiście w witrynie mogą też występować naprawdę słabe animacje. 🙂

Stara szkoła w budowie GIF

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, począwszy 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 spowodowała żadnych zmian wizualnych.
Częściowo prezentowane Tylko kompozytor; wątek główny otrzymał aktualizację wizualną, ale ta aktualizacja nie zawiera animacji wpływającej 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 żądanej głównej aktualizacji, a aktualizacja kompozytora zawiera 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. Jednym ze sposobów interpretacji tego wyniku jest uznanie go za prawdopodobieństwo obserwacji przez użytkownika. Pojedyncze upuszczone klatki mogą być nie dostrzegalne, ale mamy pewność, że jest to sekwencja wielu utraconych klatek, które wpływają na płynność ruchu.

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. Naszym zdaniem w praktyce zapewnia to użytkownikom płynne działanie treści internetowych. Do tej pory jako początkowy zestaw danych używaliśmy tych danych:

  • Średni procent utraconych wyświetleń: dla wszystkich nieaktywnych klatek animacji na całej osi czasu
  • Najgorszy odsetek utraconych klatek:zgodnie z pomiarem występujących w ciągu 1 sekundy przesuwanych okien czasu.
  • 95 centyl procentu utraconych klatek:wartość podana w odniesieniu do 1-sekundowego przesuwnego okna czasu.

Obecnie można je znaleźć w niektórych narzędziach dla deweloperów 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 narzędzie dla programistó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. Liczba klatek na sekundę w raportach dotyczy tylko wszystkich klatek, które zostały w pełni zaprezentowane.

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ń, nawet w najnowszej wersji Chrome Canary, która naszym zdaniem znacznie ułatwia debugowanie problemów z animacjami.

Obecnie zobaczysz, że klatki w przeglądarce klatek są lepiej dopasowane do granic synchronizacji pionowej i oznaczone kolorami na podstawie stanu. Nadal nie mamy pełnej wizualizacji dla wszystkich niuansów opisanych powyżej, ale planujemy dodać ich więcej w najbliższej przyszłości.

Przeglądarka ramek w Narzędziach deweloperskich w Chrome

Śledzenie w Chrome

Dzięki śledzeniu w Chrome, które jest najczęściej wybieranym narzędziem do szczegółowej analizy szczegółów, możesz zarejestrować ślad „Renderowanie treści internetowych” w nowym interfejsie Perfetto (about:tracing) i zagłębić się w procesy graficzne w Chrome. Może to być trudne zadanie, ale w niedawno dodanych do Chromium funkcjach znajdziesz kilka ułatwień. Zobacz omówienie tego, co jest dostępne w dokumencie Life of aFrame.

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 interaktywnością. 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 planujemy też opracować interfejsy API, które umożliwią wydajny pomiar płynności animacji zarówno w przypadku rzeczywistych użytkowników w terenie, jak i 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 je, oceń swoje animacje i daj nam znać, co z tego wyniknie.

Komentarze możesz wysyłać do grupy Google web-vitals-feedback, wpisując w polu tematu „[Gładkość]”. Czekamy na Twoją opinię.