ペイントは、最終的にユーザーの画面に合成されるピクセルを書き込む処理です。通常、ペイントはパイプライン内のすべてのタスクの中で最も実行時間が長いため、できるだけ避ける必要があります。
概要
- 形状または不透明度以外の任意のプロパティを変更すると、常にペイントがトリガーされます。
- ペイントは多くの場合、ピクセル パイプラインの中で最も高コストの部分です。可能であれば、使用しないでください。
- レイヤー プロモーションやアニメーションのオーケストレーションを介してペイントエリアを縮小します。
- Chrome DevTools のペイント プロファイラを使用して、ペイントの複雑さとコストを評価し、可能なものを削減します。
レイアウトとペイントがトリガーされる仕組み
任意の要素の形状を変更すると要素のピクセルの修正が必要になるため、レイアウトをトリガーすると、常にペイントがトリガーされます。
背景、テキスト色、影などの非形状プロパティを変更した場合も、ペイントをトリガーすることができます。このような場合、レイアウトは必要とされず、パイプラインは次のようになります。
Chrome DevTools を使用して、ペイントのボトルネックを迅速に識別する
Chrome DevTools を使用して、ペイントされた領域を迅速に識別することができます。[レンダリング] タブを開き、[ペイントのフラッシュ] を有効にします。
このオプションを有効にすると、ペイントが発生するたびに画面が緑色で点滅します。画面の全体、またはペイントされるべきではなかった画面領域が緑色で点滅する場合は、その原因を詳しく調査する必要があります。
移動またはフェードする要素のプロモート
ペイントは常にメモリ内の単一の画像に対して行われるわけではありません。実際、ブラウザは複数の画像、必要な場合はコンポジ層に対してペイントを行うことができます。
このアプローチには、通常は再ペイントされる要素、または変換によって画面上を移動する要素を、他の要素に影響を与えないで処理できるという利点があります。これは Sketch、GIMP、Photoshop などのアート パッケージの手法と同じであり、個々のレイヤーを他のレイヤーに対して相互に処理および合成して最終的な画像を作成することができます。
新しいレイヤを作成するための最良の方法は、will-change
CSS プロパティを使用することです。このプロパティは、すべての主要な最新ブラウザ エンジンで使用できます。transform
の値を使用すると、will-change
は新しいコンポジ層を作成します。
.moving-element {
will-change: transform;
}
ただし、各レイヤーはメモリと管理を必要とするため、あまり多くのレイヤーを作成しないように注意する必要があります。この手法の詳細については、コンポジタ専用プロパティのみの使用、およびレイヤー数の管理 セクションを参照してください。
新しいレイヤーに要素をプロモートした場合は、それによってパフォーマンス上の利点が得られたことを DevTools によって確認してください。プロファイリングなしに要素をプロモートしないでください。
ペイント エリアを縮小する
ただし、要素をプロモートしても、ペイント作業が依然として必要になる場合があります。ペイントの大きな問題は、ペイントを必要とする 2 つのエリアがブラウザによって結合されると、画面全体の再ペイントが必要になる可能性が生じることです。したがって、たとえば、ページの最上部にヘッダーを固定し、画面の最下部に何かを描くと、最終的に画面全体が再ペイントされる可能性があります。
ペイントエリアの縮小は、通常、過度のオーバーラップが生じないようにアニメーションと遷移を調整するか、ページの特定の部分のアニメーション化を避ける方法を見つける作業です。
ペイントの複雑さの簡略化
ペイントでは、特定の処理のコストが他の処理よりも高くなります。たとえば、ブラーを必要とする処理(シャドウなど)では、赤いボックスの描画などよりもペイントに時間がかかります。ただし、CSS に関しては、これは必ずしも明白でありません。background: red;
と box-shadow: 0, 4px, 4px, rgba(0,0,0,0.5);
は、パフォーマンス特性が大きく異なるようには見えませんが、実際には異なります。
上のスクリーンショットに示すように、ペイント プロファイラを使用すると、効果を実現するために他の方法を探す必要があるかどうかを判断できます。より低コストのスタイル、または目的の結果を実現する他の手法を使用できるかどうかを検討してください。
可能な場合は、特にアニメーションの実行中には常にペイントを避ける必要があります。特にモバイル機器上では、1 フレームあたり 10ms は、一般的にペイント作業を実行するのに十分長い時間ではありません。