ホームページ >ウェブフロントエンド >htmlチュートリアル >シンプルなカルーセルくじ -- CSS アニメーションの最適化_html/css_WEB-ITnose

シンプルなカルーセルくじ -- CSS アニメーションの最適化_html/css_WEB-ITnose

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

前書き

2日前に面接に行った会社で、ちょっとしたゲームについて聞かれました。インタビュアーは、赤い封筒と抽選の実施方法について、そのときのアイデアについて簡単に話しましたが、戻ってから考えてみると、それについて話しながら実行しないのは単なる悪者であるため、私はそのアイデアについて話しました。作成しました (デモとソースコード)。起動方法: ターンテーブル上で指をスライドさせると、ターンテーブルが回転します。一般的な抽選プログラムのように、バックグラウンドで抽選結果が指定されることはありません。結果は完全にあなたの手のスピードによって決まります。オンラインまたは直接の画像 デモを検索すればすぐに見つかります。 もちろん、適応性も必要です。 Rem は自己適応を実現するために使用されます。ここで設定されているのは、画面幅が 420px 未満の場合に、HTML ノードのフォント サイズを変更することで、ターンテーブルのサイズが変更されることです。画面の幅が 420px を超える場合、ターンテーブルのサイズは固定されます。 rem の自己適応の実装の詳細については、こちらを参照してください。

アニメーションとインタラクション

インターネットで見たデモのほとんどはクリックで開始されるので、インタラクション方法を変更して、タッチスクリーンのスライド方法を使用して開始したいと思いました。ここでターンテーブルを滑り速度で回転させ、回転時に負の加速度を与えて減速することは容易に考えられます。ここでユーザーエクスペリエンスに注意を払う必要があるのは、人々にスムーズな感覚を与えるために、開始速度がかなり速くなければならず、宝くじの緊迫した雰囲気を作り出すために最後にはゆっくり遅くする必要があります。したがって、加速度は最初に変化し、その後ゆっくりと変化します。これは、CSS のイーズアウトと同じ効果があります。コードは次のとおりです。

var rotate = document.getElementById('imgs');var speed = vspeed = 0,    x0 = y0 = t0 = x1 = y1 = t1 = null;(function(){    var lastTime = 0;    var vendors = ['ms', 'moz', 'webkit', 'o'];    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x){        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];    };        if(!window.requestAnimationFrame){        window.requestAnimationFrame = function(callback, element){            var currTime = new Date().getTime();            var timeToCall = Math.max(0, 16 - (currTime - lastTime));            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);            lastTime = currTime + timeToCall;            return id;        };    };        if (!window.cancelAnimationFrame){        window.cancelAnimationFrame = function(id){            clearTimeout(id);        };    };})(); // Setup requestAnimationFrame when it is unavailable.document.addEventListener('touchmove', function (e) {    e.preventDefault();});rotate.addEventListener('touchstart', function (e) {    if (e.touches.length == 1) {        x0 = e.targetTouches[0].clientX;        y0 = e.targetTouches[0].clientY;        t0 = new Date().getTime();    }});rotate.addEventListener('touchend', function (e) {    var that = this,        l = 0,        angle = 0,        timerID = null;    x1 = e.changedTouches[0].clientX;    y1 = e.changedTouches[0].clientY;    t1 = new Date().getTime();    l = Math.sqrt(Math.pow(x1-x0,2) + Math.pow(y1-y0,2));    speed = l/(t1-t0)*20;    if (speed < 10) return;    vspeed = 0.5;        var roll = function () {        angle += speed;        that.style.transform = 'rotateZ(' + angle + 'deg)';        switch (true){            case speed < -0.3:                window.cancelAnimationFrame(timerID);                return;            case speed < 10 && vspeed > 0.1:                speed -= vspeed;                vspeed -= 0.03;                break;            default:                speed -= vspeed;                break;        }        timerID = window.requestAnimationFrame(roll);    };    roll();});

ここでのアニメーションは h5 の requestAnimationFrame を使用して実装されています。 requestAnimationFrame をサポートしていないブラウザとも互換性があります。

プログラミングは非常に簡単ですが、回転全体の周期を長すぎたり短すぎたりしないようにパラメータを調整するのが最も難しい点です。終盤が速すぎると緊張感がなくなり、遅すぎると特に国内のモバイルブラウザではラグを感じてしまいます。

パフォーマンスの最適化

パフォーマンスの最適化が行われる前は、国内のモバイル ブラウザーは最適化が必要不可欠でした。

一般的な方法: レイヤ化、動的要素を静的要素から分離します。つまり、ターンテーブルが絶対的に配置され、別のレイヤーを占有します。この方法では、動的要素の変更が静的要素のレイアウトに影響を与えず、再描画が減ります。この最適化は非常に基本的なものであり、ページの作成時にすでに実装されているため、問題はここにはないことがわかります。さらに、パフォーマンスを向上させるために、CSS3d 変換メソッドが GPU レンダリング ページの使用を強制するために使用されているとよく聞いていましたが、コード内に「rotateZ()」を既に記述しており、これによりハードウェア レンダリングが有効になるはずです。何が問題なのか、どうやって解決すればいいのかわかりません。ファンタジーは役に立たないので、Chrome 開発者ですぐにテストしました:

データは実際には非常に良好で、スクリプト作成、レンダリング、描画にかかる時間は比較的妥当であることがわかりますが、問題はどこにあるのでしょうか?もちろん国産ブラウザなのでどう最適化するか? Chrome のレンダリング検出ツールを使用して見てみましょう。開く方法:

名前が示すように、最初の項目はページの描画更新 (再描画) を検出でき、2 番目の項目はレイヤー境界を表示し、3 番目の項目は FPS (フレーム/秒、FPS、フレーム レート) を表示します。 )、これらは注目すべき重要なポイントです。これは単一ページのアプリケーションであるため、後続のスクロールの問題の検出とメディアのシミュレーションはスキップされます。開始後は次のようになります:

前面の緑色のマスクは再描画領域を示し、その周囲にある茶色の円はレンダリング レイヤを示します。アニメーションを開始すると、ターンテーブル要素が表示されます。アニメーションが描画されるときに実際に再描画されるため、これが問題の鍵となるはずです。しかし、どうやって解決すればいいのでしょうか? GPU レンダリングの使用を紹介するときに、多くの記事で次の 2 つのスタイルについて言及します:

backface-visibility: hidden;perspective: 1000;


これら 2 つの文を試した後、効果はすぐに表示され、回転時に緑色の再描画ボックスは表示されなくなりました:

私は戻りました国内のモバイル ブラウザでテストしてみると、ネイティブ アプリケーションとほぼ同じように感じられなくなりました。これらの基礎となる関数を呼び出しても、パフォーマンスの違いは大きくありません。実際、最後の文のパースペクティブ: 1000 は冗長です。このように大きなパースペクティブ距離を設定するのは、3D 効果を弱め、計算量を減らすためです。ターンテーブルが回転するときは 3D 効果がありません。ここ。

主に背面の可視性: 非表示の作品。裏面は素子の裏側です。 病院で撮影したレントゲンと同じです。 両面が見えます。背中を隠すということは、裏を向いたときに何も書かれていない真っ白な状態を意味します。これが設定されていない場合、ブラウザはオブジェクトの背面もレンダリングします。ターンテーブル要素の上にポインタ要素が重ねてあるため、裏側を非表示にするように指定しないと、たとえば X 軸または Y 軸を中心に回転すると、ブラウザはターンテーブルでカバーされる範囲全体を再描画します。ターンテーブルを描画するには、ポインタも描画する必要があります。そのためには、ページの大部分を再描画する必要があります。背面を非表示にした後、レンダリング レイヤが再描画されなくなった理由については、ブラウザのレンダリング戦略に関連している可能性があります。ブラウザは最適なソリューションに従って必要なレイヤを再描画する必要があり、変更されていないレイヤは引き続き保持されます。アルゴリズム。この部分についてはまだよくわかっていません。不適切な点があればご指摘ください。


追記: backface-visibility: hidden が設定されている限り、GPU をオンにする必要はまったくなく、2D 回転を直接使用することで非常に良い結果が得られることが後でわかりました。

鄧おじいちゃんは正しい、実践が真実を試す唯一の基準だ!

参考文献:

1) Chrome での高速レンダリング: http://www.html5rocks.com/en/tutorials/speed/layers/

2) アプリのパフォーマンス検証: https://developer.mozilla 。 org/en-US/Apps/Fundamentals/Performance/App_performance_validation

3) 解放された GPU CSS3 アニメーション アクセラレーション: http://www.cnblogs.com/sunshq/p/4878019.html

4) [Web アニメーション ] CSS3 3D惑星の回転とブラウザのレンダリング原理: http://www.cnblogs.com/coco1s/p/5439619.html#3420358

5) 大画面での Web アニメーション: https://developer.mozilla.org/ zh-CN/docs /Mozilla/Firefox_OS_for_TV/Web_animations_on_large_screen

上記のコーディングは簡単ではありませんが、お気軽に「いいね!」してください

(画像提供: Xiao Zhou)

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