アニメーションの滑らかさの指標に向けて

アニメーションの測定、アニメーション フレームの考え方、ページ全体の滑らかさについて学びます。

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

ページが「スタッタリング」またはまたは「固定」スクロール中や 作成できます。こうしたエクスペリエンスはスムーズではないと Google は考えています。宛先アドレス Chrome チームはサポートの拡充に取り組んでおり、 アニメーション検出用のラボツールに改良を加え 継続的に改良を加えています Chromium 内のレンダリング パイプラインの診断に組み込まれます。

そこで、最近の進捗状況を共有し、具体的なツールに関するガイダンスを提供していきたいと考えています。 今後のアニメーションの滑らかさの指標に関するアイデアについて話し合います。これまでと同様に フィードバックをお寄せください。

この投稿では、次の 3 つの主要トピックを取り上げます。

  • アニメーションとアニメーション フレームの概要。
  • アニメーション全体の滑らかさの測定に関する現在の見解。
  • 本日のラボツールで利用できる実用的な推奨事項をいくつか紹介します。

アニメーションとは

アニメーションでコンテンツに命を吹き込む。特にレスポンスでコンテンツを移動させる アニメーションを使用すると、より自然に感じられます。 理解しやすく楽しいものにします。

ただし、アニメーションの実装が不十分だったり、追加しすぎたりすると、 エクスペリエンスを損なうことになり 明らかに面白くなくなりますおそらく誰もが 「役に立った」メッセージの数が多すぎるという移行 パフォーマンスが悪くなると 経験を悪化させかねません そのため一部のユーザーが モーションの少なさを優先する(ユーザーの好み) 重点を置くべき分野です

アニメーションの仕組み

簡単に振り返ると、レンダリング パイプラインは いくつかの連続したステージで構成されます。

  1. スタイル: スタイルを定義します。
  2. レイアウト: 各要素のジオメトリと位置を指定します。
  3. ペイント: レイヤに分割します。
  4. 複合: 画面にレイヤを追加します。

アニメーションを定義する方法は数多くありますが、基本的にはすべて 次のいずれかになります。

  • レイアウトの調整 プロパティをご覧ください。
  • ペイントの調整 プロパティをご覧ください。
  • 合成の調整 プロパティをご覧ください。

これらのステージは順次であるため、 プロパティの観点で分析できますこの更新が 費用が大きくなるほど、費用がかさみ、リスクが軽減される スムーズです(レンダリング パフォーマンス をご覧ください)。

レイアウト プロパティをアニメーション化するのは便利ですが、 コストはすぐにわかるわけではありません。アニメーションは 複合プロパティの変更で定義されています。

宣言型 CSS アニメーションの定義またはウェブの使用 アニメーション また、複合レイヤをアニメーション化したり、 プロパティ は、スムーズで効率的なアニメーションを実現するための第一歩として最適です。それでもなお、 これだけでは滑らかさは保証されません。効率的なウェブ アニメーションでさえも パフォーマンスの上限がありますだからこそ、常に測定が重要なのです。

アニメーション フレームとは

ページの視覚的な表現が更新されるまでには時間がかかります。ビジュアル 新しいアニメーション フレームが作成され、最終的に 表示されます。

更新は一定の間隔で行われるため、視覚的な更新はバッチ処理されます。多数のディスプレイ 1 秒に 60 回など、一定の間隔で更新する(つまり、 60 Hz)。最新のディスプレイでは、リフレッシュ レートが高くなる場合があります。 (90 ~ 120 Hz が一般的になってきています)。こうしたディスプレイは多くの場合、 リフレッシュ レートを柔軟に調整したり、完全に可変のフレームレートを提供したりできます。

ゲームやブラウザなどのアプリケーションの目標は、これらすべてを処理することです。 視覚的に完全なアニメーション フレームを 確認する必要がありますなお、この目標は、 重要なブラウザタスク(ネットワークからのコンテンツをすばやく読み込む、 効率的に実行できます。

どこかの時点で、すべてのビジュアル更新を ディスプレイが割り当てた期限。この場合、ブラウザは フレームが落ちた。画面が黒くなることはなく、繰り返し再生されるだけです。次のことがわかります。 前回と同じアニメーション フレームを、少し長めに 示されます。

これはよくあることです。必ずしも認識できるとは限らない 静的またはドキュメントのようなコンテンツ向けです。これはウェブ プラットフォームで一般的です。 特定できますドロップしたフレームが明らかになるのは、重要な視覚効果がある場合のみ アニメーションなどの更新は、アニメーションを安定させ続ける必要があります。 スムーズに動きます

アニメーション フレームに影響するもの

ウェブ デベロッパーは、ブラウザの機能を迅速かつ効率的に 視覚的更新を効率的にレンダリングし 表示できるようになります

例:

  • 容量が大きく、リソースを大量に消費するコンテンツを使用して、 対象デバイス。
  • 過剰な数の レイヤ GPU メモリが過剰になります。
  • 過度に複雑な CSS スタイルやウェブ アニメーションを定義する。
  • 高速レンダリングの最適化を無効にするデザイン アンチパターンを使用する。
  • メインスレッドでの JS 作業が多すぎてタスクに時間がかかり、ビジュアル あります。

では、アニメーションのフレームが期限に間に合わなかったために、 フレーム落ちでしょうか?

一つの方法として、 requestAnimationFrame() ただし、いくつかの欠点があります。requestAnimationFrame()(rAF) ブラウザに対してアニメーションの実行を指示し、 レンダリング パイプラインの次のペイント ステージの前に行うことができます。条件 コールバック関数が想定した時刻に呼び出されなかった場合、 ペイントが実行されず、1 つ以上のフレームがスキップされました。ポーリングと rAF が呼び出される頻度をカウントすると ある種のフレーム/秒を計算できます (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);

requestAnimationFrame() ポーリングの使用は、いくつかの理由からおすすめしません。

  • スクリプトごとに、独自のポーリング ループを設定する必要があります。
  • クリティカル パスを遮断する可能性がある。
  • rAF ポーリングが高速であっても、 requestIdleCallback() 長いアイドル ブロックを継続的に使用すると、 1 フレームを超えることはありません)。
  • 同様に、長いアイドル ブロックがないと、ブラウザは他のスレッドを 長時間実行タスク(長時間のガベージ コレクションや 投機的作業)。
  • ポーリングのオン / オフを切り替えると、フレーム バジェット を超えています。
  • ポーリングにより、ブラウザが 更新頻度は変動します(電源や可視性の状態などが原因)。
  • そして最も重要な点として、すべての種類のアニメーションがキャプチャされるわけではありません。 更新しました。

メインスレッドでの処理が多すぎると、アニメーション フレームを表示する機能に影響を与える可能性があります。 詳しくは、 サンプルをご覧いただき、 rAF 駆動型のアニメーションを、メインスレッド( フレーム落ち、rAF コールバックの減少、FPS の低下につながります。

メインスレッドが停滞すると、視覚的な更新が途切れ始めます。 ジャンクだ!

多くの測定ツールは主要な アニメーション フレームをスムーズに実行できます。 それだけではありません。たとえば次のようになります。

上記の動画では、長時間のタスクをメインに定期的に注入するページを示しています。 使用します。こうした時間のかかる作業は、 ビジュアル アップデートの種類によって変わります。左上に これに対応する requestAnimationFrame() の FPS が 0 に低下しました。

こうした長い作業にもかかわらず、ページはスムーズにスクロールし続けます。この なぜなら最新のブラウザでは、スクロールは スレッド形式、 完全にコンポジタによって行われます。

この例では、メイン スレッドで多数のフレーム落ちが同時に発生しています。 多数のスクロール フレームが依然として 呼び出すことができます。長いタスクが完了すると、メインスレッドのペイントが更新されます。 見た目は変わりませんrAF ポーリングではフレーム落ちが 0 に 視覚的には違いに気づかないでしょう。

アニメーション フレームの場合、話はそれほど単純ではありません。

アニメーション フレーム: 重要な更新

上記の例は、ストーリーに単なる requestAnimationFrame()

アニメーションの更新とアニメーション フレームが重要になるのは、どのような場合でしょうか。こちらの いくつか検討していますので ぜひフィードバックをお寄せください

  • メインスレッドとコンポジタ スレッドの更新
  • ペイントの更新がない
  • アニメーションの検出
  • 質と量

メインスレッドとコンポジタ スレッドの更新

アニメーション フレームの更新がブール値ではありません。フレームが他の Pod に 完全にドロップするか、完全に表示するかを選べます。アニメーションが 部分的に 表示される場合があります。つまり、1 つのリージョンに 古いコンテンツビジュアル デザインの刷新 説明します。

この問題の最も一般的な例は、ブラウザが新しい画像を生成できない場合です。 フレーム期限内にメインスレッドを更新するが、新しいコンポジタ スレッドがある (先ほどのスレッド スクロールの例など)。

宣言型アニメーションを使用して合成をアニメーション化する重要な理由の 1 つです。 推奨されるプロパティです。そうすることで、アニメーションを メインスレッドがビジー状態でも コンポジタスレッドで実行できますこれらの型 継続的に効率的に更新され あります

その一方で、メインスレッドの更新が最終的に 提示できますが、いくつかのフレーム期限を過ぎた後に限られます。現在地 ブラウザに新しいアップデートが一部適用されますが、最新のアップデートではない可能性があります。

大まかに言えば、視覚に訴える新しい更新を含むフレーム、 「部分フレーム」として表示されます。部分フレームは あります。部分的な更新には、少なくとも最も重要な 更新はアニメーションのようなもので、 呼び出すことができます

ペイントの更新がない

部分的な更新のもう一つのタイプは、画像などのメディアが終了していない場合です。 フレーム表示に間に合うように デコードとラスタライズをする必要があります

また、ページがまったく静的な状態でも、ブラウザでレンダリングに遅れが生じることがあります。 高速スクロールによる視覚的な更新。これは、ピクセルのレンダリングが GPU メモリを節約するために、可視ビューポートを超えるコンテンツは破棄されることがあります。これは、 ピクセルのレンダリングに時間がかかり、1 つのフレームよりも 大きなスクロールの後ですべてをレンダリングする(指でフリングしたときのように)これは一般的に これはチェッカーボードと呼ばれます。

フレーム レンダリングの機会ごとに、レンダリングされたフレームの 最新のビジュアル更新が画面に表示されますそれを実現できるかどうかを測定する をフレーム スループットといいます。

GPU の処理が本当に滞っていると、ブラウザ(またはプラットフォーム)が ビジュアル アップデートの試行頻度を抑制し、 測定します。技術的にはそうすればドロップ数を減らせますが 低いフレーム スループットとして見えます。

とはいえ、フレーム スループットの低下が必ずしも悪いわけではありません。ページがほぼアイドル状態の場合 アクティブなアニメーションがなく 低フレームレートでも 高フレームレートで魅力的に映りがちです(しかもバッテリーの節約にもなります)。

では、どのような場合にフレーム スループットが重要になるのでしょうか。

アニメーションの検出

高いフレーム スループットが重要となるのは、 使用できます。アニメーションの種類は、 特定のスレッド(メイン、コンポジタ、ワーカー)に割り当てられ、 そのスレッドが期限内に更新を提供することに依存しています。私たちは スムーズさに影響するアクティブなアニメーションが そのスレッドの更新に依存します

アニメーションの種類によっては、定義と検出が容易なものもあります。 宣言型アニメーション、つまりユーザー入力ドリブン アニメーションは、 JavaScript 駆動型アニメーションと比較した場合の、アニメーション化可能な style プロパティ。

requestAnimationFrame() さんと一緒に すべての rAF 呼び出しが必ずしも視覚的な 更新またはアニメーション化できます。たとえば、フレームレートを追跡するためだけに rAF ポーリングを使用します。 (上図を参照)平滑度の測定には影響がないはずです。 更新されません。

質と量

最後に、アニメーションとアニメーション フレームの更新の検出は、依然として アニメーションの更新回数しか捉えられず、 向上します

たとえば、動画の視聴中にフレームレートが 60 fps が安定している場合があります。 動画をご覧ください。技術的にはこれは完全にスムーズですが、動画自体に 低ビットレート、ネットワーク バッファリングの問題などが考えられます。これは アニメーションの滑らかさの指標に直接影響しますが、 できます。

<canvas> を利用するゲーム( 画面外 canvas を 安定したフレームレートを確保すること) という観点から見ると 高品質のゲームアセットを読み込むのに失敗します。 レンダリング アーティファクトが表示されます。

もちろん、サイトによっては不適切なアニメーションが表示されることもあります 🙂?

準備中の旧校の GIF

当時はすごくクールだったと思うよ!

単一のアニメーション フレームの状態

フレームが部分的に表示されたり、フレーム落ちが発生したりすることが スムーズさに影響しないものなので、各フレームに 完全性スコアまたは平滑度スコアです

ここに示したのは、1 つの Pod の状態を アニメーション フレームを最適なものから順に並べます。

更新不要 アイドル時間。前のフレームの繰り返し。
すべて表示 メインスレッドの更新が期限内にコミットされたか、または 必要だったかどうかがわかります。
一部表示 コンポジタのみメインスレッドの更新の遅延にビジュアル エラーが あります。
一部表示 コンポジタのみビジュアル アップデートがありましたが、 滑らかさに影響するアニメーションがアップデートに含まれていませんでした。
一部表示 コンポジタのみメインスレッドで視覚的な更新が行われ、 以前から古いフレームが届いたため、代わりに使用されました。
一部表示 コンポジタのみ必要なメイン アップデートがない場合、 コンポジタの更新に、滑らかさに影響するアニメーションが含まれています。
一部表示 コンポジタのみですが、コンポジタの更新には 滑らかさに影響するアニメーションです。
フレーム落ち 更新なし。コンポジタの更新は必要なく、main の更新は 対応が遅れています
フレーム落ち コンポジタの更新が必要でしたが、更新が遅れました。
古いフレーム 必要な更新はレンダラによって生成されたものでしたが、 vsync の期限までに GPU がまだ表示されませんでした。

これらの状態を、ある程度のスコアに変えることができます。おそらくもう一つは、 このスコアを解釈するための確率は、 できます。1 つのドロップされたフレームはそれほど観測できないかもしれませんが、 連続して滑らかさに影響する、落ちたフレームがたくさんあるのは確かです。

まとめ: ドロップフレームの割合の指標

場合によっては各ソリューションの状態を アニメーション フレームを作成したいときは、「一目で」スコア 提供します

フレームは部分的に表示されることがあり、完全にスキップされても フレームの更新は実際にはスムーズさに影響しない可能性があるため、 フレームのカウントなど、ブラウザが認識できない範囲の 重要なタイミングで視覚的に完全なアップデートを提供する。

メンタルモデルは以下から移行する必要があります。

  1. フレーム/秒:
  2. アニメーションの欠落や重要な更新を検出し、
  3. 特定の期間におけるドロップ率

重要なのは、重要なタスクを待機する時間の割合、 。これは、ユーザーがスムーズに操作できるようにする自然な方法と一致すると考えています。 実践しているウェブコンテンツの割合ですこれまでは、 指標の初期セット:

  • Average Percent Dropped:全期間における、アイドル状態でないすべてのアニメーション フレームの タイムライン全体
  • フレーム ドロップの割合の最悪ケース: 1 秒間のスライドで測定。 指定することもできます。
  • ドロップしたフレームの割合の 95 パーセンタイル: 1 秒間で測定。 スライディングウィンドウにできます

このスコアは現在、一部の Chrome デベロッパー ツールで確認できます。これらは、 全体のフレーム スループットにのみ注目しているので、その他の指標も たとえばフレーム レイテンシなどの要因に重点を置いています。

デベロッパー ツールで実際に試してみましょう。

パフォーマンス HUD

Chromium のきれいな Performance HUD が旗の背後に隠されている (chrome://flags/#show-performance-metrics-hud)。このページには Core Web Vitals などのスコアと、いくつかの試験運用版の定義も示されます。 時間経過に伴うドロップされたフレームの割合に基づくアニメーションの滑らかさ。

パフォーマンス HUD

フレーム レンダリングの統計情報

[Frame Rendering] を有効にする 統計情報」 DevTools の [Rendering settings] で、新しいアニメーション フレームのライブビューを表示する 部分更新と完全にドロップされたフレームを区別するために色分けされています。 あります。レポートされる fps は、完全に表示されたフレームのみに対するものです。

フレーム レンダリングの統計情報

DevTools のパフォーマンス プロファイル記録のフレーム ビューア

DevTools のパフォーマンス パネルに 以前からフレームは 閲覧者 しかし 最新のレンダリングパイプラインとは 少し同期がとれていませんでした 確認します最近は多くの改良が加えられており、 Chrome Canary 版。アニメーションの問題のデバッグが大幅に容易になると考えています。

現在では、フレーム ビューアでフレームの位置と整合性が vsync の境界線を表し、ステータスに基づいて色分けされます。空き容量がありません 概要を示していますが、今後さらに追加していく予定です。 説明します

Chrome DevTools のフレーム ビューア

Chrome トレース

最後に Chrome Tracing を使用して、 「ウェブ コンテンツ レンダリング」の新しい Perfetto を使用してトレースを UI(または about:tracing)を確認し、Chrome の 示しています。大変な作業かもしれませんが 簡単に利用できるようになりました。Chronicle の概要と フレーム ドキュメントをご覧ください。

トレース イベントから、次のことを確実に特定できます。

  • 実行中のアニメーション(TrackerValidation という名前のイベントを使用)。
  • アニメーション フレームの正確なタイムラインを取得する( PipelineReporter)。
  • アニメーションでジャンクが発生する場合は、 (内部のイベント内訳を使用して) PipelineReporter イベント)。
  • 入力ドリブン アニメーションの場合、ビジュアルが更新されるまでの時間を確認する (EventLatency という名前のイベントを使用)。

Chrome トレース パイプライン レポーター

次のステップ

Web Vitals イニシアチブは、 優れたユーザーエクスペリエンスを ウェブで構築できます ラボベースの指標(合計 ブロック時間(TBT)は 潜在的なインタラクティビティの問題を検出して診断する今後、 アニメーションの滑らかさに関して、同様のラボベースでの指標を設計します。

アプリのデザインに関するアイデアが見つかり次第、随時 個々のアニメーション フレームデータに基づいて作成されます。

将来的には、Google の API を設計し、 アニメーションの滑らかさとパフォーマンスが向上します。 フィールドをご覧ください。 そちらでも最新情報を随時ご確認ください。

フィードバック

最近の改良やデベロッパーツールには アニメーションの滑らかさを測定できます。これらのツールをぜひお試しください アニメーションのベンチマークを実施し、その方向性をお知らせください。

自分のコメントは web-vitals-feedback Google 「[平滑度指標]」を持つグループ」と入力します。私たちは ぜひご意見をお寄せください。