ホームページ >ウェブフロントエンド >htmlチュートリアル >[Webアニメーション] CSS3 3D惑星運動とブラウザレンダリング原理_html/css_WEB-ITnose

[Webアニメーション] CSS3 3D惑星運動とブラウザレンダリング原理_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-24 11:19:301125ブラウズ

前回の記事:【CSS3 Advanced】かっこいい3D回転パース の続きです。

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

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

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

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

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

ランダムなスクリーンショット 1 枚の写真:

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

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

1. 前の記事で作成した 3D 写真の壁をプロトタイプとして使用し、それを修正します。 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 ブラウザに関するものです。

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

transform API の代わりにtransform3d API を使用し、GPU アクセラレーションの開始を強制します

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

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

2. DOM ツリーを構築する (DOM ツリー) 3. レンダー ツリーを構築する (レンダー ツリー)

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

このレンダリング プロセスは、基本的な知識については、以下に進みます。

ページがロードされて解析されると、ブラウザーで非常によく知られた構造である DOM (Document Object 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 アニメーションにとって非常に重要です。通常、Chrome はレイヤーのコンテンツをテクスチャとして GPU にアップロードします。 。コンテンツが変更されない場合は、レイヤーを再ペイントする必要はありません。

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

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

3D またはパースペクティブ変換 (perspective、transform) CSS プロパティ

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

  • 3D (WebGL) コンテキストがあるまたは高速化された 2D コンテキスト 5ba626b379994d53f7acf72a64f9b697 要素
  • プラグインの混合 (Flash など)
  • 独自の不透明度での CSS アニメーション、またはアニメーション化された変換要素の使用
  • 高速化された CSS フィルターを備えた要素
  • 複合レイヤーを備えた要素 子孫ノード (言い換えれば、要素には、独自のレイヤー内に子要素があります)
  • その要素には、複合レイヤーを含む、より低い Z インデックスを持つ兄弟要素があります (つまり、要素は複合レイヤーでレンダリングされています)
  • レイヤーの再描画
  • 静的 Web ページの場合、レイヤーは最初に描画された後は変更されませんが、Web アニメーションの場合、ページの DOM 要素は常に変更されます。レイヤーのコンテンツが変更された場合、はい、変換プロセス中に変更があった場合、レイヤーは再描画されます。 強力な Chrome 開発者ツールは、アニメーション ページの実行中にどのコンテンツが再描画されたかを確認できるツールを提供します:

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

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

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

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

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

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

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

    概要

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

  • ブラウザはHTMLを解析し、DOMを取得して複数のレイヤーに分割します(GraphicsLayer)
  • 各レイヤーのノードのスタイル結果を計算します(スタイルの再計算 -- スタイルの再計算)
  • 各ノードのグラフィックと位置を生成します(レイアウト - -リフローと再レイアウト)
  • 各ノードの描画をレイヤーのビットマップに塗りつぶします (ペイント設定とペイント - 再描画)
  • レイヤーをテクスチャとして GPU にアップロードします
  • 複数のレイヤーに準拠します ページ上に最終的な画面イメージを生成します (複合レイヤー - レイヤーの再編成)
  • Web アニメーションのコストの大部分はレイヤーの再描画にあり、レイヤーベースの複合モデルはレンダリング パフォーマンスに大きな影響を与えます。描画が必要ない場合、複合操作のオーバーヘッドは無視できるほどであるため、レンダリングのパフォーマンスの問題をデバッグしようとするときの最初の目標は、レイヤーの再描画を回避することです。これにより、アニメーションのパフォーマンスを最適化する方向が決まり、要素の再描画とリフローが削減されます。

    リフローと再ペイント

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

    リフロー

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

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

    Repaint

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

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

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

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

  • ウィンドウのサイズ変更
  • フォントの変更(フォントの変更)
  • スタイルシートの追加または削除(スタイルシートの追加または削除)
  • ユーザーのテキスト入力などのコンテンツの変更入力ボックス (ユーザーが入力ボックスにテキストを入力するなど、コンテンツが変更されます)
  • 次のような CSS 疑似クラスをアクティブ化します。 hover (IE での兄弟ノード疑似クラスのアクティブ化) (次のような CSS 疑似クラスのアクティブ化) :hover (IE では兄弟の疑似クラスのアクティブ化))
  • クラス属性の操作 (クラス属性の操作)
  • DOM を操作するスクリプト (DOM を操作するスクリプト)
  • offsetWidth 属性と offsetHeight 属性の計算 ( offsetWidth と offsetHeight を計算します
  • style 属性のプロパティを設定します
  • したがって、ページの場合、私たちの目的は、ページのリフローと再描画を最小限に抑えることです。 簡単な例:
  • // 下面这种方式将会导致回流reflow两次var newWidth = aDiv.offsetWidth + 10; // ReadaDiv.style.width = newWidth + 'px'; // Writevar newHeight = aDiv.offsetHeight + 10; // ReadaDiv.style.height = newHeight + 'px'; // Write// 下面这种方式更好,只会回流reflow一次var newWidth = aDiv.offsetWidth + 10; // Readvar newHeight = aDiv.offsetHeight + 10; // ReadaDiv.style.width = newWidth + 'px'; // WriteaDiv.style.height = newHeight + 'px'; // Write

    リフローと再描画を減らすことは、実際には意味します。レンダリング ツリーでの操作 (複数の DOM とスタイル変更のマージ) を減らし、一部のスタイル情報の要求を減らし、ブラウザーの最適化戦略を最大限に活用します。

    キューをフラッシュ

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

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

    offsetTop、offsetLeft、offsetWidth、offsetHeight

  • scrollTop/Left/Width/Height

  • clientTop/Left / width/height

  • width,height

  • リクエストされたgetComputedStyle()、またはIEのcurrentStyle

  • この時点で、最も正確な情報をフィードバックするために、ブラウザはすぐにリフローおよび再描画して、次のことを確認する必要があります。当社の情報は正確であるため、フラッシュ キューが早期に実行される可能性があります。
  • display:none と Visibility:hidden

    どちらもページ上のノードを非表示にすることができます。違いは

  • display:none 隐藏后的元素不占据任何空间。它的宽度、高度等各种属性值都将“丢失”
  • visibility:hidden 隐藏的元素空间依旧存在。它仍具有高度、宽度等属性值
  • 从性能的角度而言,即是回流与重绘的方面,

  • display:none  会触发 reflow(回流)
  • visibility:hidden  只会触发 repaint(重绘),因为没有发现位置变化
  • 他们两者在优化中 visibility:hidden 会显得更好,因为我们不会因为它而去改变了文档中已经定义好的显示层次结构了。

    对子元素的影响:

  • display:none 一旦父节点元素应用了 display:none,父节点及其子孙节点元素全部不可见,而且无论其子孙元素如何设置 display 值都无法显示;
  • visibility:hidden 一旦父节点元素应用了 visibility:hidden,则其子孙后代也都会全部不可见。不过存在隐藏“失效”的情况。当其子孙元素应用了 visibility:visible,那么这个子孙元素又会显现出来。
  •  

       动画的性能检测及优化

    耗性能样式

    不同样式在消耗性能方面是不同的,譬如 box-shadow 从渲染角度来讲十分耗性能,原因就是与其他样式相比,它们的绘制代码执行时间过长。这就是说,如果一个耗性能严重的样式经常需要重绘,那么你就会遇到性能问题。其次你要知道,没有不变的事情,在今天性能很差的样式,可能明天就被优化,并且浏览器之间也存在差异。

    因此关键在于,你要借助开发工具来分辨出性能瓶颈所在,然后设法减少浏览器的工作量。

    好在 chrome 浏览器提供了许多强大的功能,让我们可以检测我们的动画性能,除了上面提到的,我们还可以通过勾选下面这个 show FPS meter 显示页面的 FPS 信息,以及 GPU 的使用率:

     

    使用 will-change 提高页面滚动、动画等渲染性能

    官方文档说,这是一个仍处于实验阶段的功能,所以在未来版本的浏览器中该功能的语法和行为可能随之改变。

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

    will-change: autowill-change: scroll-positionwill-change: contentswill-change: transform        // Example of <custom-ident> will-change: opacity          // Example of <custom-ident>will-change: left, top        // Example of two <animateable-feature>will-change: unsetwill-change: initialwill-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 変換は、translate3D、scaleZ などの GPU アクセラレーションを有効にします。もちろん、私たちのページには 3D 変換がない可能性がありますが、GPU アクセラレーションを有効にできないという意味ではなく、3D 変換以外の変換でも使用できます。ページ、これは操作の一種と考えられます。実際には Z 軸の変更は必要ありませんが、ブラウザを騙すために宣言したふりをします。

    参考:

    レンダリング: 再描画、リフロー/再レイアウト、再スタイル

    スクロールパフォーマンス

    MDN--will-change

    WebKitでレイアウトをトリガーする方法(しない)

    ハイパフォーマンスアニメーション

    Chrome での高速レンダリング

    3D 回転球体を作成する CSS3

    この記事はこれで終わりです。まだ質問や提案がある場合は、オリジナルの記事です。才能が浅いです 記事に何か間違いがあればお知らせください。

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

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

    この記事が役に立った場合は、「おすすめ」をクリックしてください。記事を書くのは簡単ではありません。

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