不必要な塗料を避ける - GIF アニメーション版

特にモバイルでは、スムーズなフレームレートを実現するためにペイントを回避することが重要です。ただし、塗料が思いもよらない場所に飛散することもあります。この記事では、アニメーション GIF によって不要なペイントが発生する理由と、適用できる非常に簡単な修正方法について説明します。

愛らしさの層

ご存じのとおり、最新のブラウザでは、DOM 要素のグループをレイヤと呼ばれる個別の「画像」にペイントすることがあります。ページ全体に 1 つのレイヤがある場合もあれば、数百、まれに数千のレイヤがある場合もあります。

DOM 要素がレイヤにグループ化され、要素の 1 つが視覚的に変更されると、変更された要素だけでなく、変更された要素と重複するレイヤ内の他のすべての要素もペイントする必要があります。あるものを別のものの上にペイントすると、上書きされたピクセルは事実上「失われる」ことになります。元のピクセルを復元するには、ペイントし直す必要があります。

そのため、1 つの要素を他の要素から分離して、ペイント時に変更していない他の要素を再ペイントしないようにすることがあります。たとえば、固定ページ ヘッダーとスクロール可能なコンテンツを組み合わせる場合、コンテンツがスクロールされるたびに、ヘッダーと新たに表示されるコンテンツを再描画する必要があります。ヘッダーを別のレイヤに配置すると、ブラウザでスクロールを最適化できます。スクロールすると、ブラウザは GPU の助けを借りてレイヤを移動し、どちらのレイヤも再描画しないようにできます。

レイヤを追加するたびにメモリ使用量が増加し、パフォーマンス オーバーヘッドも増加するため、パフォーマンスを維持しながら、ページをできるだけ少ないレイヤにグループ化することが目標です。

アニメーション GIF とは何の関係があるの?

次の画像をご覧ください。

4 つのレイヤに分割されたウェブアプリ。
図 1: 4 つのレイヤに分割されたウェブアプリ。

これは、シンプルなアプリの可能性のあるレイヤ設定です。4 つのレイヤがあり、そのうち 3 つ(レイヤ 2 ~ 4)はインターフェース要素です。後ろのレイヤはローダーで、アニメーション GIF です。通常のフローでは、アプリの読み込み中にローダー(レイヤ 1)を表示し、すべてが完了したら他のレイヤを表示します。ただし、アニメーション GIF を非表示にする必要があります

でも、なぜ非表示にしなければならないのですか?

いい質問ですね。理想的には、ブラウザが GIF の可視性をチェックし、自動的にペイントしないようにするだけです。残念ながら、アニメーション GIF が画面に隠れているか、表示されているかをチェックすることは、通常、単に描画するよりも費用がかかるため、描画されます。

最適な場合、GIF は独自のレイヤにあり、ブラウザは GIF をペイントして GPU にアップロードするだけで済みます。最悪の場合、すべての要素が 1 つのレイヤにグループ化され、ブラウザはすべての要素を再描画する必要があります。処理が完了しても、すべてを GPU にアップロードする必要があります。ユーザーが GIF を見ることができないにもかかわらず、この処理は GIF のフレームごとに行われます。

デスクトップでは、CPU と GPU がより強力で、両者間でデータを転送するための十分な帯域幅があるため、この種のペイント動作でも問題ない可能性があります。ただし、モバイルではペイントは非常にコストがかかるため、慎重に行う必要があります。

この変更が影響するブラウザ

通常どおり、動作はブラウザによって異なります。現在、Chrome、Safari、Opera では、GIF が隠されていてもすべて再描画されます。一方、Firefox は GIF が隠れているため再描画する必要がないことを認識します。Internet Explorer はブラックボックスのようなものであり、IE11 でも F12 ツールはまだ開発中であるため、再描画が行われているかどうかを示す兆候はありません。

この問題が発生しているかどうかを確認するにはどうすればよいですか?

最も簡単な方法は、Chrome DevTools の [ペイント レイヤを表示] を使用することです。DevTools を読み込み、右下の歯車アイコン(歯車アイコン)を押して、[レンダリング] セクションの [ペイントの長方形を表示] を選択します。

Chrome DevTools でペイントの矩形を表示する機能の有効化
図 2: Chrome DevTools で [ペイント レイヤの表示] を有効にする

次のような赤い長方形を探すだけです。

DevTools のペイント長方形を表示機能は、アニメーション GIF の問題を赤い長方形で示唆します。
図 3: DevTools の [塗りつぶし領域を表示] で、アニメーション GIF の問題が赤い長方形で示されています。

画面上の小さな赤いボックスは、Chrome が何かを再描画していることを示します。他の要素の背後にローダー GIF が隠れていることはわかっています。そのため、このような赤いボックスが表示されたら、表示されている要素を非表示にして、アニメーション GIF が回転しているかどうかを確認する必要があります。ある場合は、CSS または JavaScript を挿入して、その要素またはその親要素に display: none または visibility: hidden を適用する必要があります。もちろん、背景画像のみの場合は、必ず削除してください。

実際のサイトでこの動作の例を確認するには、Allegro をご覧ください。各商品の画像には、明示的に非表示にするのではなく、ぼかしを入れたローダー GIF が表示されています。

まとめ

60 fps を達成するには、ページのレンダリングに必要なことのみを行う必要があります。この目標を達成するには、余分な塗料を除去することが重要です。アニメーション GIF を実行したままにすると、不要なペイントがトリガーされることがあります。これは、DevTools のペイント矩形を表示ツールで簡単に検出してデバッグできます。

子猫のアニメーション ローダ GIF をずっと再生したままにしておいたわけではありませんよね?