ホームページ  >  記事  >  ウェブフロントエンド  >  CSS3 3D 惑星の回転とブラウザーのレンダリング原理の使用に関する詳細な紹介

CSS3 3D 惑星の回転とブラウザーのレンダリング原理の使用に関する詳細な紹介

高洛峰
高洛峰オリジナル
2017-03-19 16:44:191734ブラウズ

最近Webアニメーションにハマったので、学習過程を記録して皆さんと共有したいと思います。

CSS3 3D 惑星回転デモ ページをクリックしてください: デモ。 (Chrome を使用して開くことをお勧めします)

この記事の完全なコードとその他の CSS3 効果は、私の Github で見ることができます。星を付けていただければ幸いです。

まあ、デモを開けない人もいるかもしれないし、ページがめちゃくちゃになっている人もいるかもしれません。以下にいくつかのレンダリングを示します: (写真は少し大きいので、しばらくお待ちください)

CSS3 3D 惑星運動レンダリング。

CSS3 3D 行星运转动画,太阳系动画

私が撮ったランダムなスクリーンショット:

CSS3 3D 行星运转动画,太阳系动画

結局のところ、CSS3 3D の魅力を体験するには、デモ ページをクリックすることを強くお勧めします。

それでは、この CSS3 3D 惑星運動アニメーションの制作プロセスについては詳しく説明しません。この記事の焦点は Web アニメーションの導入とパフォーマンスの最適化です。 CSS3 3D の詳細については、以前のブログ「[CSS3 Advanced] クールな 3D 回転パース」を参照してください。シンプルなアイデア:

1. 前の記事で作成した 3D 写真の壁をプロトタイプとして使用し、それを修正します。

2. 各球体を作成するためのさまざまな方法を考え、最終的にこの妥協案を使用しました。 CSS3 の 3D 形状。次に、制作プロセス中に Sass を使用して CSS を作成すると、CSS アニメーションを作成する面倒なプロセスの多くを削減できます。

3. デモでは、Javascript を使用してこのイベントを削除しました。惑星運動アニメーション自体は純粋な CSS で実装されています。

この記事では、パフォーマンスの最適化の観点から、ブラウザーのレンダリングと表示、ブラウザーの再描画と再配置、アニメーションのパフォーマンス検出の最適化などの原則について説明します。

ブラウザー レンダリングの原則と Web アニメーションの表示とアプリケーションの影響

サブタイトルは少し大きいですが、ブラウザごとにカーネル (レンダリング エンジン) が異なることはわかっています。たとえば、最も主流の Chrome ブラウザのカーネルは Blink カーネル ( Chrome (28 以降) 以降のバージョン)、Opera (15 以降のバージョン) および Yandex ブラウザ)、Firefox は Gecko、IE は Trident、ブラウザ カーネルは Web ページの構文の解釈と Web ページのレンダリング (表示) を担当します。異なるブラウザ カーネルの動作原理は完全に一貫しているわけではありません。

実際、以下で主に説明するのは、Chrome ブラウザーでのレンダリング原理です。 Chrome カーネルのレンダリングについては検証可能な情報がたくさんあるため、他のカーネルを使用したブラウザについては結論を導き出すことは敢えてしません。そのため、以下の説明はデフォルトで Chrome ブラウザに関するものです。

まず最初に結論をいくつか挙げておきます:

m3dにはtransを使用しますapiを変換APIの代わりに、GPUアクセラレーションの開始を強制します

ここではGPUアクセラレーションについて話します、なぜGPUが3Dをアクセラレートできるのか変換?これらはすべて、ブラウザーの基本的なレンダリングから開始する必要があります。ブラウザーで Web ページをレンダリングして表示するプロセスは決まりきったものであり、面接では次のように分けられます。

1. HTML の解析 (HTML パーサー)。

2. DOM ツリーの構築 (DOM ツリー)

3. レンダー ツリーの構築 (レンダー ツリー)

非常に古典的な画像を見つけました:

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍は基本的な知識なので、さらに深めてください。

ページがロードされて解析されると、ブラウザーで非常によく知られた構造、DOM (

Document

Object Model、ドキュメント オブジェクト モデル) を表します。ブラウザがページをレンダリングするとき、開発者には公開されない多くの中間表現が使用されます。その最も重要な構造はレイヤーです。 この記事の焦点はこのレイヤーです:

Chrome には、RenderLayer (DOM サブツリーを担当)、GraphicsLayer (RenderLayer のサブツリーを担当) というさまざまな種類のレイヤーがあります。次に、GraphicsLayer レイヤーについて説明します。

GraphicsLayer レイヤーはテクスチャとして GPU にアップロードされます。

このテクスチャはここで非常に重要です。それで、

テクスチャとは何ですか?

ここでのテクスチャとは GPU 用語を指します。メイン メモリ (RAM など) から画像メモリ (GPU の VRAM など) に移動されるビットマップ イメージと考えてください。 GPU に移動したら、それをメッシュ ジオメトリに合わせ、Chrome でテクスチャを使用して、ページ コンテンツの大部分を GPU から取得できます。非常に単純な長方形のグリッドにテクスチャを適用することで、さまざまな位置や変形を簡単に一致させることができます。これが 3D CSS の仕組みです。 理解するのは難しいですが、Chrome では、前述の GraphicsLayer の概念がわかります。開発者ツールで、次の選択を行って、レイヤー境界線の表示オプションを表示します:

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍 非常に単純なページでは、以下に示すように、このページにはレイヤーが 1 つだけあることがわかります。青いグリッドはタイルを表しており、(レイヤーではなく) レイヤーの単位として考えることができます。Chrome では、要素自体のレイヤーの

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍 ページを作成します。上記は非常に単純で、レイヤーは生成されませんが、非常に複雑なページでは、たとえば、要素に 3D CSS プロパティを設定して要素を変換すると、要素に独自のレイヤーがあると、どのように見えるかがわかります。のように。

このビューでレイヤーの輪郭を示すオレンジ色の境界線に注目してください:

レイヤーの作成はいつトリガーされますか?

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍上の図の黄色の枠で囲まれたレイヤーは、Web アニメーションにとって非常に重要な GraphicsLayer です。通常、Chrome はレイヤーのコンテンツをテクスチャとして GPU にアップロードする前に 1 ビットに描画します。コンテンツが変更されない場合は、レイヤーを再ペイントする必要はありません。

これの重要な点は、再描画に費やした時間を JavaScript の実行など、他のことに使用できることです。描画時間が非常に長い場合、アニメーションの失敗や遅延も発生します。

では、要素はいつレイヤーの作成をトリガーするのでしょうか?現時点では、次の条件のいずれかが満たされた場合にレイヤーが作成されます。

3D または遠近変換 (perspective、transform) CSS プロパティ

  • ビデオのデコードを高速化する 39000f942b2545a5315c57fa3276f220 要素を使用する

  • f542fbc2780e49e5956b7ee698c43520 要素に 3D (WebGL) コンテキストまたはアクセラレーションされた 2D コンテキストがあります

  • プラグイン (Flash など) を混合する

  • 独自の不透明度で CSS アニメーションを実行するか、アニメーション変換要素を使用します

  • にはAccelerate CSS

    Filter
  • 要素があります
  • 要素には複合レイヤーを含む子孫ノードがあります(つまり、要素には独自のレイヤー内に子要素があります)

  • 要素には

    zがあります-index
  • 下位で複合レイヤーを含む兄弟要素 (つまり、要素は複合レイヤーの上にレンダリングされます)
  • レイヤーの再描画

  • 静的 Web ページの場合、レイヤーが最初に表示されます。描画後に変更されることはありませんが、Web アニメーションの場合、ページの DOM 要素は変換プロセス中にレイヤーの内容が変更されると、レイヤーが再描画 (再描画) されます。

強力な Chrome 開発者ツールは、アニメーション ページの実行中にどのコンテンツが再描画されたかを確認できるツールを提供します:

Chrome の古いバージョンでは、ペイント四角形を表示するオプションがあります。ページのどのレイヤーが再描画され、赤い枠線でマークされているか。

しかし、Chrome の新しいバージョンではこのオプションが削除されたようです。現在のオプションはペイント フラッシュを有効にすることであり、これも Web サイトの動的変更を識別し、緑色の枠線でマークされています。

上の図を見ると、ページ上にいくつかの緑色のボックスがあり、再描画が行われたことがわかります。 Chrome は常にレイヤー全体を再描画するわけではなく、DOM の無効な部分をインテリジェントに再描画しようとすることに注意してください。

論理的には、ページ上で非常に多くのアニメーションが発生しているため、再描画は非常に頻繁に行われるはずですが、上記の惑星アニメーションでは、いくつかの緑色の再描画ボックスしか見えませんでした。1 つは GPU の最適化であり、もう 1 つは GPU の最適化です。アニメーション ページ全体のレイヤーが 1 つだけの場合、変形にはtransformを使用することになり、必然的にページの再描画が必要になりますが、レイヤー化(GraphicsLayer)技術を使用すると、上記のような状況に応じた要素がレイヤーを作成します。このとき、このレイヤーの回転変換は他のレイヤーに影響を与えないため、このレイヤーを再描画する必要はありません。 (個人的な意見ですので、ご了承ください。)

Web アニメーションのパフォーマンスを最適化するには、レイヤーの再描画を理解することが重要です。

無効化と強制再描画の原因は何ですか?境界失敗につながる状況は数多くあるため、この質問に網羅的に答えるのは困難です。最も一般的な状況は、CSS スタイルを操作して DOM を変更するか、リフローを引き起こすことです。

再描画とリフローの根本原因を見つける最良の方法は、開発者ツールのタイムラインとペイント フラッシュ ツールの有効化を使用して、再描画/リフローの直前に DOM が変更された場所を見つけることです。

概要

では、ブラウザは DOM 要素から最終アニメーションまでどのように表示するのでしょうか?

  • ブラウザはHTMLを解析し、DOMを取得して複数のレイヤーに分割します(GraphicsLayer)

  • 各レイヤーのノードのスタイル結果を計算します(スタイルの再計算 – スタイルの再計算)

  • 各ノードに対して生成グラフィックスと位置 (レイアウト - リフローと再レイアウト)

  • 各ノードをレイヤーのビットマップに描画して塗りつぶします (ペイント セットアップとペイント - 再描画)

  • レイヤーをテクスチャとして GPU にアップロードします

  • は と互換性がありますページ上に複数のレイヤーを配置して最終的な画面イメージを生成します (複合レイヤー – レイヤーの再編成)

Web アニメーションのコストの大部分はレイヤーの再描画にあり、レイヤーベースの複合モデルがパフォーマンスのレンダリングを担当します。広範囲にわたる影響を及ぼします。描画が必要ない場合、複合操作のオーバーヘッドは無視できるほどであるため、レンダリングのパフォーマンスの問題をデバッグしようとするときの最初の目標は、レイヤーの再描画を回避することです。これにより、アニメーションのパフォーマンスを最適化する方向が決まり、要素の再描画とリフローが削減されます。

リフローとリペイント

ここでは、まずリフローとリフローという 2 つの概念を区別する必要があります。

リフロー

要素のサイズ、レイアウト、非表示などの変更により、レンダー ツリーの一部 (またはすべて) を再構築する必要がある場合。これをリフロー、つまり再レイアウトといいます。

すべてのページを少なくとも 1 回リフローする必要があります。これは、ページが初めてロードされるときです。リフロー中、ブラウザはレンダリング ツリーの影響を受けた部分を無効にし、リフローが完了した後、影響を受けた部分を画面に再描画します。このプロセスは再描画と呼ばれます。

再ペイント

レンダーツリー内の一部の要素で属性を更新する必要がある場合、これらの属性は要素の外観とスタイルにのみ影響し、背景色などのレイアウトには影響しません。それを再描画といいます。

リフローは確実に再描画を引き起こしますが、再描画は必ずしもリフローを引き起こすわけではないことに注意してください。

明らかに、リフローのコストは大きくなります。簡単に言うと、要素を操作するとその要素のサイズや位置が変更され、リフローが発生します。

リフローがトリガーされる場合:

// 下面这种方式将会导致回流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 とスタイルの変更をマージする) を減らし、一部のスタイル情報のリクエストを減らし、ブラウザーの最適化戦略を最大限に活用することを意味します。

flushQueue

実際、ブラウザ自体に最適化戦略があり、DOM をリフローして再描画するためにあらゆる Javascript が使用される場合、ブラウザはそれに耐えられない可能性があります。したがって、多くのブラウザはこれらの操作を最適化するため、キューを維持し、キュー内の操作が特定の数または一定の時間間隔に達すると、リフローと再描画を引き起こすすべての操作をこのキューに入れます。フラッシュされ、バッチが処理されます。これにより、複数のリフローと再描画が 1 つのリフローと再描画に変わります。

ただし、次のような特定のスタイル情報を正確に取得する必要がある場合があるため、例外もあります。

スクロール上/左/幅/高さ


クライアント上/左/幅/高さ



幅,高さ



はgetComputedStyle()、またはIEの

current

Style

  • 現時点で、最も正確な情報をフィードバックするために、ブラウザはすぐにリフローして再描画して、提供された情報が確実に反映されるようにする必要があります。は正確であるため、フラッシュ キューが事前に実行される可能性があります。


display

:none と

visibility
:hidden

    の両方で、ページ上のノードを非表示にすることができます。違いは、
  • display:none 非表示要素がスペースを占有しないことです。その幅、高さ、その他の属性値は「失われます」

visibility:hidden 非表示の要素スペースはまだ存在します。高さや幅などの属性値はまだ保持されています

パフォーマンスの観点、つまりリフローと再描画の観点から見ると、

display:none はリフロー (リフロー) をトリガーしません

visibility: hidden のみ 位置の変更が見つからないため、再描画がトリガーされます
  • どちらも、最適化中に表示が良くなります。
  • 子要素への影響:

display:none display:none が親ノード要素に適用されると、親ノードとその子孫ノード要素はすべて非表示になり、その子孫要素の表示値がどのようなものであっても、設定すると表示できなくなります。

  • visibility:hidden 一度親ノード要素に適用すると、その子孫もすべて非表示になります。しかし、隠れた「失敗」も存在します。子孫要素に Visibility:visible を適用すると、子孫要素が再び表示されます。

  • アニメーションのパフォーマンスの検出と最適化

  • パフォーマンスを消費するスタイル

たとえば、box-shadow はレンダリングの観点から見ると、パフォーマンスの消費が非常に大きいためです。スタイル、その描画コードの実行に時間がかかりすぎます。これは、パフォーマンスを重視するスタイルを頻繁に再描画する必要がある場合、パフォーマンスの問題が発生することを意味します。次に、変わらないものは何もなく、今日パフォーマンスが悪いスタイルでも明日には最適化される可能性があり、ブラウザーごとに違いがあることを知っておく必要があります。

したがって、重要なのは、開発ツールを使用してパフォーマンスのボトルネックを特定し、ブラウザのワークロードを軽減する方法を見つけることです。
  • 幸いなことに、Chrome ブラウザには、上記のアニメーション パフォーマンスに加えて、以下の FPS メーターの表示をチェックすることで、ページの FPS 情報や GPU 使用率を表示できる強力な機能が多数用意されています。

  • ページのスクロールやアニメーションなどのレンダリングパフォーマンスを向上させるには、will-changeを使用してください。

公式ドキュメントには、これはまだ実験段階にある機能であると記載されているため、この機能の構文はブラウザの将来のバージョンでも同じになるため、動作が変更される可能性があります。

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

使用方法示例:(具体每个取值的意义,去翻翻文档)

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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。