他の人が言ったように、普遍的に最適なアプローチはありません。それは、レンダリングする必要があるものの詳細、頻度、およびグラフィック コンポーネント間で発生する必要があるメッセージングに依存するためです。
確かに DOM リフローはコストがかかりますが、この包括的な警告が常に当てはまるとは限りません。たとえば、position:fixed; を使用します。要素は、ページのリフローのトリガーを回避します (固定されていない子がある場合、必ずしも要素内にあるとは限りません)。再描画は (これが間違っている場合は訂正してください) ピクセルのプッシュであるためコストが高く、同じ数のピクセルをキャンバスにプッシュするよりも本質的に遅くはありません。ものによっては、より高速になる場合があります。さらに、それぞれには、他の操作よりもパフォーマンス上の利点がある特定の操作があります。
考慮すべき点を次に示します。
多くの A グレードのブラウザーで、WebGL で高速化されたキャンバス要素を使用することがますます可能になっています。これは 2D では問題なく動作し、描画操作が GPU に送信されるという利点があり、これは 2D コンテキストよりもはるかに高速です。ただし、これは一部のターゲット プラットフォームでは利用できない場合があります (たとえば、この記事の執筆時点では、iOS Safari では利用できますが、ハイブリッド モバイル アプリケーションをターゲットとする場合に使用される iOS UIWebView では利用できません)。キャンバスをラップするライブラリを使用すると、これを抽象化できます。利用可能な場合は WebGL を使用します。pixi.js を見てください。
逆に、DOM には CSS3 アニメーション/トランジションがあり、通常は GPU によって自動的にハードウェア アクセラレーションされます (WebGL に依存しません)。アニメーションの種類によっては、キャンバスを使用するよりもこの方法の方がはるかに高速な結果を得ることができ、多くの場合、より単純なコードを使用できます。
最終的には、ソフトウェア パフォーマンスの原則として、使用されるアルゴリズムを理解することが重要です。つまり、どのアプローチを使用するかに関係なく、アニメーション フレームをどのようにスケジューリングするのでしょうか? どの処理に最も時間がかかるかをプロファイラーで確認したことはありますか? このプラクティスは、何がパフォーマンスに影響を与えているかを理解するのに優れています。
私は複数のアニメーションを含むアプリに取り組んでおり、各コンポーネントを DOM とキャンバスの両方として実装しています。最初は、DOM バージョンがキャンバス (KineticJS でラップされた) バージョンよりもパフォーマンスが高いことに驚きましたが、これはすべてのアニメーション化された要素が position:fixed であり、CSS (jQuery UI を介してボンネットの下で) を使用していたためであることはわかっています。 GPU パフォーマンスを取得します。ただし、これらの要素を管理するコードは扱いにくいと感じました (私の場合は ymmv)。キャンバス アプローチを使用すると、よりピクセル パーフェクトなレンダリングが可能になりますが、CSS でスタイルを設定する機能が失われます (技術的にはピクセル パーフェクト レンダリングも可能になりますが、実現するのは多かれ少なかれ複雑になる可能性があります)。
最も複雑なアニメーションをより低いフレームレートに調整することで大幅な速度向上を達成しました。これは、私の場合は 60fps バージョンと見分けがつきませんが、古い iPad 2 ではバターのようにスムーズに動作します。希望のフレームレートよりも。これを DOM 上の CSS アニメーションで行うのは困難です (繰り返しますが、多くの場合、これらは本質的に高速です)。私が次に見ているのは、複数のキャンバスベースのコンポーネントを同じ requestAnimationFrame ループに同期することです (おそらく個別に調整されるか、各コンポーネントがフレームレートの設定された割合を取得するラウンドロビン アプローチで、2 ~ 3 回は問題なく動作する可能性があります)。要素 (ちなみに、
また、プロファイリングを行い、GUI とは関係のないコード内の 1 つのクラスが、プロパティを計算するために非常に頻繁に呼び出される特定のメソッドを持っていることを確認することで、大幅な速度向上を実現しました。問題のクラスは不変だったので、メソッドを変更して値をメモすると、CPU 使用率が半分に低下しました。Chrome DevTools とフレーム チャートに感謝します。いつもプロフィール。
ほとんどの場合、更新されるピクセル数が最大のボトルネックになる傾向がありますが、GPU でそれを行うことができれば、コードのすべての CPU を効果的に取り戻したことになります。DOM リフローは避けるべきですが、これは DOM を避けるという意味ではありません。一部の要素は、DOM (テキストなど) を使用してレンダリングする方がはるかに簡単であり、キャンバスよりもブラウザー (または OS) のネイティブ コードによって最適化される場合があります。最後に、いずれかのアプローチ (DOM またはキャンバス) を使用して特定のコンポーネントで許容できるパフォーマンスを得ることができる場合は、そのタイプのコンポーネントを管理するためのコードを最も単純にする方法を使用してください。
最良のアドバイスは、さまざまなアプローチで分離された部分を試し、プロファイラーで実行し、テクニックを使用してオーバードローするか、制限をプッシュして、どのアプローチが最も速く実行できるかを確認し、必要になる前に最適化しないことです。このルールの警告は、あなたが尋ねている質問です:どの技術的アプローチが最高のパフォーマンスを可能にするかを事前に知るにはどうすればよいですか? 答えの仮定に基づいて 1 つを選択すると、基本的に時期尚早に最適化することになり、これが引き起こす恣意的な痛みに耐えることになります。代わりに、アプリケーションのニーズに焦点を当てたラピッド プロトタイピングまたは (さらに良い) 制御された実験によって選択している場合は、R&D を行っていることになります:)