ホームページ >ウェブフロントエンド >htmlチュートリアル >CSS3 オープニングアニメーション制作と最適化例_html/css_WEB-ITnose
期待される効果: http://v.youku.com/v_show/id_XMjY2NTc1MzYw.html
最初にこのアニメーションを作らなければならなかったとき、私は実際に断りました。なぜなら、アニメーションの知識が豊富でも、これだけの材料だけでは始められないからです。そんなある日、ワウ・レギオンのCGアニメーションを見て、あるアイデアが頭に浮かびました。
「重い雲を抜けて、昼から夜への変化とともに、ロゴは遠くから現れて、すぐに画面に向かって移動し、ロゴが画面いっぱいに表示されようとしたとき、星が点滅して遠くに消えました...」
それで私は凸凹の旅を始めました。オープニングアニメーションの。
クラウド レイヤーの作成:
この期間中に、CSS を使用してクラウド レイヤーをシミュレートするいくつかのブログ投稿と例を読みました。例を以下に示します。
モバイル クラウド: https://codepen.io/montanaflynn/pen/orxwK
3D クラウド: https://www.clicktorelease.com/blog/how- to-make-clouds-with -css-3d
実際、単一の画像を使用して雲をシミュレートするには、いくつかの経験上の問題があります。たとえば、画像によって生成された雲を通過しようとすると、次のようになります。感覚はしばらく消えてしまうので、ユーザーにとっては問題になりますが、視覚的なギャップがあり、実際の雲のレイヤーは領域であるため、5枚の写真を使用して方向を変えて雲を生成しました。雲は三次元シーンに膨らみを感じさせます。
以下は Jaume Sanchez Elias によって書かれた 3D クラウド生成コードです:
function createCloud() { vardiv = document.createElement('div'); div.className = 'cloudBase'; // 随机定位当前云团位置 var t = 'translateX( ' + random_x + 'px ) ' + 'translateY( ' + random_y + 'px ) ' + 'translateZ( ' + random_z + 'px )'; div.style.transform = t; world.appendChild(div); for (varj = 0; j < 5 + Math.round(Math.random() * 10); j++) { varcloud = document.createElement('div'); cloud.className = 'cloudLayer'; // 随机产生云层的'translateX/translateY/translateZ/rotateZ/scale // CSS值,这里是云团充实感的关键实现 cloud.data = { x: random_x, y: random_y, z: random_z, a: random_a, s: random_s }; var t = 'translateX( ' + random_x + 'px ) ' + 'translateY( ' + random_y + 'px ) ' + 'translateZ( ' + random_z + 'px ) ' + 'rotateZ( ' + random_a + 'deg ) ' + 'scale( ' + random_s + ' )'; cloud.style.transform = t; div.appendChild(cloud); layers.push(cloud); } return div;}
上記の方法を使用してクラウド レイヤーを出力すると、雲の強い質感。アニメーションの読み込みを高速化するために、生成されたクラウド レイヤーをページ内の固定 DOM の形式で記述しました。これにより、初期の JS 消費が最小限に抑えられ、画像の読み込みが最初に実行されます。ページの読み込み中。クラウド DOM を作成したら、雲の中を移動するエフェクトの作成を開始できます。移動のプロセスには、背景色を昼から夜に変更するエフェクトも含まれます。これにより、この移動アクションを実現できます。時間の経過とともに画面が変化します。雲を通過する効果を完成させるためにコードは次のように実装されます (ここでは Webkit バージョンのコードのみが示されています):
@-webkit-keyframes angular { 0% { -webkit-transform: translateZ(300px); opacity: 1; } 100% { -webkit-transform: translateZ(570px); opacity: 1; }} @-webkit-keyframes dayToNight { 0% { background-color: #007fd5; opacity: 1; } 100% { background-color: #000; opacity: 1; }}
スターライトとロゴ:
ロゴとスターライト レンダリング処理は拡大と拡大縮小の処理であり、スケールを変更することで実現できます。
/* 星光场景 */@-webkit-keyframes starsense { 0% { -webkit-transform: scale(1); opacity: 0; } 30% { -webkit-transform: scale(25); opacity: 1; } 90% { -webkit-transform: scale(0); opacity: 1; } 100% { -webkit-transform: scale(0); opacity: 0; }}/* logo场景 */@-webkit-keyframes logosense { 0% { -webkit-transform: scale(0); transform: scale(0); opacity: 1; } 20% { -webkit-transform: scale(1); transform: scale(1); } 85% { -webkit-transform: scale(1); transform: scale(1); opacity: 1; -webkit-filter: blur(0); } 100% { -webkit-transform: scale(100); transform: scale(100); opacity: 0; -webkit-filter: blur(50px); }}となります。
パフォーマンスの最適化:
アニメーションのパフォーマンスが比較的大きな問題であることがテストで判明したため、比較的低い構成の一部のマシンではフレーム ドロップやフリーズが多く発生するため、パフォーマンスの最適化を実行する必要があります。
Chrome のタイムライン ツールを使用してアニメーションの実行パフォーマンスをチェックしたところ、アニメーションの実行サイクル中にレンダリングと再描画によって多くのリソースが消費され、JS も消費することがわかりました。アニメーションの実行サイクル中に大量のリソースを取得したので、最初にアニメーションの読み込み関数を振り返ってみました。
function loadOpenSenseAnimation() { isStart = true; openSense.className += ' begin'; world.className += ' begin'; logoSense.className += ' begin'; setTimeout(function() { viewPort.className = ' begin'; }, 4000); loadingAudio === 0 && Audio.play(); openSense.addEventListener("webkitAnimationEnd", function(){ // 动画结束时事件 console.log('动画执行结束啦!'); if (openSense) { // 执行完就抹除 openSense.parentNode.removeChild(openSense); } }, false); }
このようになりました:
function loadOpenSenseAnimation() { Settings.isStart = true; $container.className += ' animated'; $mask.addEventListener("webkitAnimationStart", function() { // 动画开始时候播放 if (Settings.isVoice && Settings.loadingAudio === 0) { Settings.AudioPlayer.play(); } }, false); $container.addEventListener("webkitAnimationEnd", function(animation) { // 动画结束时事件 if (animation.animationName === Settings.EndingAnimatedName) { OpenSense.pass(); } }, false); }
ここでは、setTimeout 関数を削除し、アニメーション遅延を使用して setTimeout の位置を引き継ぎ、JS 消費の影響を最小限に抑えるために複数の DOM 操作を 1 つにマージしました。アニメーションのサウンド再生は、webkitAnimationStart イベントを使用して音楽とアニメーションを同期させて監視されます (ここでは、webkitAnimationEnd/webkitAnimationStart の使用に注意する必要があります。このイベントは、各子ノードのアニメーションが開始および終了するときにトリガーされます。アニメーションイベントが必要かどうかを判断するには、animationName を判断する必要があります)、次にタイムラインを再度使用して確認しました:
アニメーションの実行中に、以前のレンダリングと再描画と相まって、クラウド レイヤー以降のフレーム数が少ない 時間占有率が高すぎるため、当初は CSS 属性の不適切な使用と判断されました。そこで、CSS アニメーションで使用される属性を調べました。
タイムライン フレーム ドロップの時間セグメントに従って、この期間中に有効になった CSS 属性と組み合わせると、いくつかの属性がパフォーマンスに影響を与える可能性がある マークを付けて除去テストを実施した結果、ブラーがパフォーマンス低下の主な要因であることが判明したため、CSS で除去の最適化を実行して、ブラー、重複、または不要な属性を除去しました。
最適化の結果:
複数の最適化の後、タイムラインを通じて次の結果が得られました。ページ読み込みの開始時にいくつかのドロップされたフレームを除いて、残りは基本的に安定していることがわかります。アニメーションはロゴで固定され 3 秒ほど停止したため、この間は 60 フレームありませんでした。
オンラインの例: http://huangxingbang.github.io/openSense/cloud.html
概要:
1. アニメーションの場合は、GPU が作業を共有できるようにする不透明度/変換/回転/スケール属性を使用してみてください。
2. アニメーションでの setTimeout の制御を放棄します。アニメーションの再生タイミングの制御は、アニメーションの遅延を使用して実装されます。正確な制御が必要な場合は、RequestAnimationFrame を使用してアニメーションを更新します。
3. webkitAnimationStart/webkitAnimationEnd を使用してアニメーション並列タスクの開始/終了を制御します。
参考:
フロントエンドのパフォーマンスの最適化 (CSS アニメーション): https://segmentfault.com/a/1190000000490328
高パフォーマンスの CSS3 アニメーション: https://www.qianduan.net/high-performance- css3- アニメーション/