ホームページ > 記事 > ウェブフロントエンド > CSS3 3D 惑星の回転とブラウザーのレンダリング原理の使用に関する詳細な紹介
最近Webアニメーションにハマったので、学習過程を記録して皆さんと共有したいと思います。
CSS3 3D 惑星回転デモ ページをクリックしてください: デモ。 (Chrome を使用して開くことをお勧めします)
この記事の完全なコードとその他の CSS3 効果は、私の Github で見ることができます。星を付けていただければ幸いです。
まあ、デモを開けない人もいるかもしれないし、ページがめちゃくちゃになっている人もいるかもしれません。以下にいくつかのレンダリングを示します: (写真は少し大きいので、しばらくお待ちください)
CSS3 3D 惑星運動レンダリング。
私が撮ったランダムなスクリーンショット:
結局のところ、CSS3 3D の魅力を体験するには、デモ ページをクリックすることを強くお勧めします。
それでは、この CSS3 3D 惑星運動アニメーションの制作プロセスについては詳しく説明しません。この記事の焦点は Web アニメーションの導入とパフォーマンスの最適化です。 CSS3 3D の詳細については、以前のブログ「[CSS3 Advanced] クールな 3D 回転パース」を参照してください。シンプルなアイデア:
1. 前の記事で作成した 3D 写真の壁をプロトタイプとして使用し、それを修正します。
2. 各球体を作成するためのさまざまな方法を考え、最終的にこの妥協案を使用しました。 CSS3 の 3D 形状。次に、制作プロセス中に Sass を使用して CSS を作成すると、CSS アニメーションを作成する面倒なプロセスの多くを削減できます。
3. デモでは、Javascript を使用してこのイベントを削除しました。惑星運動アニメーション自体は純粋な CSS で実装されています。
この記事では、パフォーマンスの最適化の観点から、ブラウザーのレンダリングと表示、ブラウザーの再描画と再配置、アニメーションのパフォーマンス検出の最適化などの原則について説明します。
サブタイトルは少し大きいですが、ブラウザごとにカーネル (レンダリング エンジン) が異なることはわかっています。たとえば、最も主流の Chrome ブラウザのカーネルは Blink カーネル ( Chrome (28 以降) 以降のバージョン)、Opera (15 以降のバージョン) および Yandex ブラウザ)、Firefox は Gecko、IE は Trident、ブラウザ カーネルは Web ページの構文の解釈と Web ページのレンダリング (表示) を担当します。異なるブラウザ カーネルの動作原理は完全に一貫しているわけではありません。
実際、以下で主に説明するのは、Chrome ブラウザーでのレンダリング原理です。 Chrome カーネルのレンダリングについては検証可能な情報がたくさんあるため、他のカーネルを使用したブラウザについては結論を導き出すことは敢えてしません。そのため、以下の説明はデフォルトで Chrome ブラウザに関するものです。
まず最初に結論をいくつか挙げておきます:
ここではGPUアクセラレーションについて話します、なぜGPUが3Dをアクセラレートできるのか変換?これらはすべて、ブラウザーの基本的なレンダリングから開始する必要があります。ブラウザーで Web ページをレンダリングして表示するプロセスは決まりきったものであり、面接では次のように分けられます。
1. HTML の解析 (HTML パーサー)。
2. DOM ツリーの構築 (DOM ツリー)
3. レンダー ツリーの構築 (レンダー ツリー)
非常に古典的な画像を見つけました:
は基本的な知識なので、さらに深めてください。
ページがロードされて解析されると、ブラウザーで非常によく知られた構造、DOM (
DocumentObject Model、ドキュメント オブジェクト モデル) を表します。ブラウザがページをレンダリングするとき、開発者には公開されない多くの中間表現が使用されます。その最も重要な構造はレイヤーです。 この記事の焦点はこのレイヤーです:
Chrome には、RenderLayer (DOM サブツリーを担当)、GraphicsLayer (RenderLayer のサブツリーを担当) というさまざまな種類のレイヤーがあります。次に、GraphicsLayer レイヤーについて説明します。
GraphicsLayer レイヤーはテクスチャとして GPU にアップロードされます。
このテクスチャはここで非常に重要です。それで、
ここでのテクスチャとは GPU 用語を指します。メイン メモリ (RAM など) から画像メモリ (GPU の VRAM など) に移動されるビットマップ イメージと考えてください。 GPU に移動したら、それをメッシュ ジオメトリに合わせ、Chrome でテクスチャを使用して、ページ コンテンツの大部分を GPU から取得できます。非常に単純な長方形のグリッドにテクスチャを適用することで、さまざまな位置や変形を簡単に一致させることができます。これが 3D CSS の仕組みです。 理解するのは難しいですが、Chrome では、前述の GraphicsLayer の概念がわかります。開発者ツールで、次の選択を行って、レイヤー境界線の表示オプションを表示します:
非常に単純なページでは、以下に示すように、このページにはレイヤーが 1 つだけあることがわかります。青いグリッドはタイルを表しており、(レイヤーではなく) レイヤーの単位として考えることができます。Chrome では、要素自体のレイヤーの
ページを作成します。上記は非常に単純で、レイヤーは生成されませんが、非常に複雑なページでは、たとえば、要素に 3D CSS プロパティを設定して要素を変換すると、要素に独自のレイヤーがあると、どのように見えるかがわかります。のように。
上の図の黄色の枠で囲まれたレイヤーは、Web アニメーションにとって非常に重要な GraphicsLayer です。通常、Chrome はレイヤーのコンテンツをテクスチャとして GPU にアップロードする前に 1 ビットに描画します。コンテンツが変更されない場合は、レイヤーを再ペイントする必要はありません。
では、要素はいつレイヤーの作成をトリガーするのでしょうか?現時点では、次の条件のいずれかが満たされた場合にレイヤーが作成されます。
3D または遠近変換 (perspective、transform) CSS プロパティ
ビデオのデコードを高速化する 39000f942b2545a5315c57fa3276f220 要素を使用する
f542fbc2780e49e5956b7ee698c43520 要素に 3D (WebGL) コンテキストまたはアクセラレーションされた 2D コンテキストがあります
独自の不透明度で CSS アニメーションを実行するか、アニメーション変換要素を使用します
にはAccelerate CSS
Filter要素には
zがあります-indexしかし、Chrome の新しいバージョンではこのオプションが削除されたようです。現在のオプションはペイント フラッシュを有効にすることであり、これも Web サイトの動的変更を識別し、緑色の枠線でマークされています。
上の図を見ると、ページ上にいくつかの緑色のボックスがあり、再描画が行われたことがわかります。 Chrome は常にレイヤー全体を再描画するわけではなく、DOM の無効な部分をインテリジェントに再描画しようとすることに注意してください。
論理的には、ページ上で非常に多くのアニメーションが発生しているため、再描画は非常に頻繁に行われるはずですが、上記の惑星アニメーションでは、いくつかの緑色の再描画ボックスしか見えませんでした。1 つは GPU の最適化であり、もう 1 つは GPU の最適化です。アニメーション ページ全体のレイヤーが 1 つだけの場合、変形にはtransformを使用することになり、必然的にページの再描画が必要になりますが、レイヤー化(GraphicsLayer)技術を使用すると、上記のような状況に応じた要素がレイヤーを作成します。このとき、このレイヤーの回転変換は他のレイヤーに影響を与えないため、このレイヤーを再描画する必要はありません。 (個人的な意見ですので、ご了承ください。)
Web アニメーションのパフォーマンスを最適化するには、レイヤーの再描画を理解することが重要です。
無効化と強制再描画の原因は何ですか?境界失敗につながる状況は数多くあるため、この質問に網羅的に答えるのは困難です。最も一般的な状況は、CSS スタイルを操作して DOM を変更するか、リフローを引き起こすことです。
再描画とリフローの根本原因を見つける最良の方法は、開発者ツールのタイムラインとペイント フラッシュ ツールの有効化を使用して、再描画/リフローの直前に DOM が変更された場所を見つけることです。
では、ブラウザは DOM 要素から最終アニメーションまでどのように表示するのでしょうか?
ブラウザはHTMLを解析し、DOMを取得して複数のレイヤーに分割します(GraphicsLayer)
各レイヤーのノードのスタイル結果を計算します(スタイルの再計算 – スタイルの再計算)
各ノードに対して生成グラフィックスと位置 (レイアウト - リフローと再レイアウト)
各ノードをレイヤーのビットマップに描画して塗りつぶします (ペイント セットアップとペイント - 再描画)
レイヤーをテクスチャとして GPU にアップロードします
は と互換性がありますページ上に複数のレイヤーを配置して最終的な画面イメージを生成します (複合レイヤー – レイヤーの再編成)
Web アニメーションのコストの大部分はレイヤーの再描画にあり、レイヤーベースの複合モデルがパフォーマンスのレンダリングを担当します。広範囲にわたる影響を及ぼします。描画が必要ない場合、複合操作のオーバーヘッドは無視できるほどであるため、レンダリングのパフォーマンスの問題をデバッグしようとするときの最初の目標は、レイヤーの再描画を回避することです。これにより、アニメーションのパフォーマンスを最適化する方向が決まり、要素の再描画とリフローが削減されます。
ここでは、まずリフローとリフローという 2 つの概念を区別する必要があります。
要素のサイズ、レイアウト、非表示などの変更により、レンダー ツリーの一部 (またはすべて) を再構築する必要がある場合。これをリフロー、つまり再レイアウトといいます。
すべてのページを少なくとも 1 回リフローする必要があります。これは、ページが初めてロードされるときです。リフロー中、ブラウザはレンダリング ツリーの影響を受けた部分を無効にし、リフローが完了した後、影響を受けた部分を画面に再描画します。このプロセスは再描画と呼ばれます。
レンダーツリー内の一部の要素で属性を更新する必要がある場合、これらの属性は要素の外観とスタイルにのみ影響し、背景色などのレイアウトには影響しません。それを再描画といいます。
リフローは確実に再描画を引き起こしますが、再描画は必ずしもリフローを引き起こすわけではないことに注意してください。
明らかに、リフローのコストは大きくなります。簡単に言うと、要素を操作するとその要素のサイズや位置が変更され、リフローが発生します。
ウィンドウのサイズ変更
:hover などの CSS pseudo-class をアクティブ化します ( :hover などの CSS 疑似 class のアクティブ化 (IE では兄弟の疑似クラスのアクティブ化))
と offsetHeight プロパティの計算 (offsetWidth と offsetHeight の計算)
// 下面这种方式将会导致回流reflow两次 var newWidth = ap.offsetWidth + 10; // Read ap.style.width = newWidth + 'px'; // Write var newHeight = ap.offsetHeight + 10; // Read ap.style.height = newHeight + 'px'; // Write // 下面这种方式更好,只会回流reflow一次 var newWidth = ap.offsetWidth + 10; // Read var newHeight = ap.offsetHeight + 10; // Read ap.style.width = newWidth + 'px'; // Write ap.style.height = newHeight + 'px'; // Write
上の 4 つの文は offsetHeight 操作が含まれるため、ブラウザは 2 回リフローを強制しますが、次の 4 つの文は offset 操作を組み合わせるため、1 ページのリフローが削減されます。
リフローと再描画を減らすということは、実際には、レンダリング ツリーでの操作 (複数の DOM とスタイルの変更をマージする) を減らし、一部のスタイル情報のリクエストを減らし、ブラウザーの最適化戦略を最大限に活用することを意味します。
実際、ブラウザ自体に最適化戦略があり、DOM をリフローして再描画するためにあらゆる Javascript が使用される場合、ブラウザはそれに耐えられない可能性があります。したがって、多くのブラウザはこれらの操作を最適化するため、キューを維持し、キュー内の操作が特定の数または一定の時間間隔に達すると、リフローと再描画を引き起こすすべての操作をこのキューに入れます。フラッシュされ、バッチが処理されます。これにより、複数のリフローと再描画が 1 つのリフローと再描画に変わります。
ただし、次のような特定のスタイル情報を正確に取得する必要がある場合があるため、例外もあります。
スクロール上/左/幅/高さ
クライアント上/左/幅/高さ
幅,高さ
はgetComputedStyle()、またはIEの
Style
display
visibility
:hidden
visibility:hidden 非表示の要素スペースはまだ存在します。高さや幅などの属性値はまだ保持されています
使用方法示例:(具体每个取值的意义,去翻翻文档)
will-change: auto will-change: scroll-position will-change: contents will-change: transform // Example of <custom-ident> will-change: opacity // Example of <custom-ident> will-change: left, top // Example of two <animateable-feature> will-change: unset will-change: initial will-change: inherit // 示例 .example{ will-change: transform; }
will-change 为 web 开发者提供了一种告知浏览器该元素会有哪些变化的方法,这样浏览器可以在元素属性真正发生变化之前提前做好对应的优化准备工作。 这种优化可以将一部分复杂的计算工作提前准备好,使页面的反应更为快速灵敏。
值得注意的是,用好这个属性并不是很容易:
不要将 will-change 应用到太多元素上:浏览器已经尽力尝试去优化一切可以优化的东西了。有一些更强力的优化,如果与 will-change 结合在一起的话,有可能会消耗很多机器资源,如果过度使用的话,可能导致页面响应缓慢或者消耗非常多的资源。
有节制地使用:通常,当元素恢复到初始状态时,浏览器会丢弃掉之前做的优化工作。但是如果直接在样式表中显式声明了 will-change 属性,则表示目标元素可能会经常变化,浏览器会将优化工作保存得比之前更久。所以最佳实践是当元素变化之前和之后通过脚本来切换 will-change 的值。
不要过早应用 will-change 优化:如果你的页面在性能方面没什么问题,则不要添加 will-change 属性来榨取一丁点的速度。 will-change 的设计初衷是作为最后的优化手段,用来尝试解决现有的性能问题。它不应该被用来预防性能问题。过度使用 will-change 会导致大量的内存占用,并会导致更复杂的渲染过程,因为浏览器会试图准备可能存在的变化过程。这会导致更严重的性能问题。
给它足够的工作时间:这个属性是用来让页面开发者告知浏览器哪些属性可能会变化的。然后浏览器可以选择在变化发生前提前去做一些优化工作。所以给浏览器一点时间去真正做这些优化工作是非常重要的。使用时需要尝试去找到一些方法提前一定时间获知元素可能发生的变化,然后为它加上 will-change 属性。
使用 transform3d api 代替 transform api,强制开始 GPU 加速
GPU 能够加速 Web 动画,这个上文已经反复提到了。
3D transform 会启用GPU加速,例如 translate3D, scaleZ 之类,当然我们的页面可能并没有 3D 变换,但是不代表我们不能启用 GPU 加速,在非 3D 变换的页面也使用 3D transform 来操作,算是一种 hack 加速法。我们实际上不需要z轴的变化,但是还是假模假样地声明了,去欺骗浏览器。
以上がCSS3 3D 惑星の回転とブラウザーのレンダリング原理の使用に関する詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。