6

JavaScript のフェードとトランジションを含む複雑なアニメーション シーケンスがあります。一度に変化する 4 つの要素で構成されるこのシーケンスでは、setTimeout各要素で a が使用されます。

Internet Explorer 9 でテストしたところ、アニメーションはリアルタイムで動作します (所要時間は 1.6 秒で、正確には 1.6 秒かかりました)。他のブラウザではアニメーション時間が 4 秒 (Firefox 3 および 4、Chrome、Opera) で、IE 8 以下では 20 秒ほどかかります。

他のすべてのブラウザーが泥沼にはまって動けない中、IE9 はどのように高速化できるのでしょうか?

私は要素を 1 つにマージして、いつでも 1 つの setTimeout を持つようにする方法を見つけようとしましたが、残念ながら、干渉 (別のリンクをクリックして新しいアニメーションを開始する前に開始するなど) には耐えられません。現在のものは終了しています)。

編集:コメントに応じて詳しく説明するために、コードの概要を次に示します。

link.onclick = function() {
    clearTimeout(colourFadeTimeout);
    colourFadeTimeout = setTimeout("colourFade(0);",25);

    clearTimeout(arrowScrollTimeout);
    arrowScrollTimeout = setTimeout("arrowScroll(0);",25);

    clearTimeout(pageFadeOutTimeout);
    pageFadeOutTimeout = setTimeout("pageFadeOut(0);",25);

    clearTimeout(pageFadeInTimeout);
    pageFadeInTimeout = setTimeout("pageFadeIn(0);",25);
}

4 つの関数はそれぞれ、フェードを 1 フレームずつ進めてから、アニメーションの終了まで、引数をインクリメントして別のタイムアウトを設定します。

http://adamhaskell.net/cw/index.html (ユーザー名: knockknock; パスワード: goaway)でページを見ることができます(サウンドと音楽があり、無効にすることができますが、注意してください!) - 私の JavaScript は非常にきちんと整理していないのでごちゃごちゃしていますが、少しコメントされているので、一般的なアイデアが何であるかを理解していただければ幸いです。

4

2 に答える 2

13

いくつかのこと:

  1. タイムアウトは 25ms です。これは 40 fps に変換されます。これは、javascript を介して達成しようとする非常に高いフレームレートです。特に、リフローを引き起こす可能性のある DOM 操作を含むものについては。50 または 60 に増やします。15 fps は、実行している種類のアニメーションには十分に流動的です。ここにビデオを表示しようとしているのではなく、ページ内で物を移動するだけです。

  2. の最初のパラメータとして文字列を使用しないでくださいsetTimeout()。性能重視なら特に。これにより、JavaScript はアニメーションのフレームごとに文字列を再コンパイルするようになります。代わりに関数を使用してください。引数を渡す必要がある場合は、無名関数を使用して、実行する関数をラップします。

    setTimeout(function(){
        pageFadeIn(0)
    },50);
    

    これは、スクリプトがロードされたときに一度だけコンパイルされます。

  3. Ben が述べたように、単一の setTimeout を使用して関数をスケジュールする方が安価です。さらに言えば、代わりに setInterval を使用すると、コードの明瞭さが向上する場合があります (コーディング スタイルによっては、そうでない場合もあります)。


追加の回答:

JavaScript アニメーションのプログラミングは、最適化と妥協がすべてです。ページ上の多くのものをほとんど遅くせずにアニメーション化することは可能ですが、それを正しく行う方法を知り、何を犠牲にするかを決める必要があります。一度にどれだけアニメーション化できるかを示す例として、私が数年前に書いたリアルタイム戦略ゲームのデモがあります。

ゲームを最適化するために私が行ったことの中には、次のものがあります。

  1. 歩く兵士は 2 つのアニメーション フレームだけで構成されており、2 つの画像を切り替えるだけです。しかし、それにもかかわらず、その効果は非常に説得力があります。完璧なアニメーションは必要ありません。説得力のあるものだけが必要です。

  2. すべてに単一の setInterval を使用します。CPUに関しては安価で、管理が簡単です。基本フレーム レートを決定し、異なるアニメーションが異なる時間に開始されるようにスケジュールするだけです。

于 2010-11-18T03:29:42.920 に答える
3

まあ、それはたくさんのjavascriptです(「4倍の素晴らしさ」にもかかわらず:)

あなたは多くのsetTimeoutシーケンスを起動しています.JSエンジンがこれに対してどれだけ最適化されているかわかりません..特にIE <= 8

わかりました、大まかな提案かもしれません...小さなタイミングエンジンを書くことができるかもしれません。

現在実行中の時限イベントを保存するグローバルオブジェクトを、実行する関数と遅延...

次に、そのグローバル オブジェクトをチェックする単一の setTimeout ハンドラを用意し、反復ごとに遅延を減らし、遅延が 0 未満になったときに関数を呼び出します。

グローバルイベントは次のようになります。

var events = {

        fade1 : {
            fn : func_name,
            delay : 25,
            params : {}
        }

        fadeArrow : {
            fn : func_name,
            delay : 500,
            params : {}
        }

        slideArrow : {
            fn : func_name,
            delay : 500,
            params : {
                arrow:some_value
            }
        }

    }

次に、これらを一定間隔(おそらく10または20ミリ秒)でループする関数を作成し、それらが完了するまで遅延を減らし、paramsを関数のパラメーターとして使用して関数を起動します(Function.callを確認してください)。

ダウンしたら、同じ遅延で setTimeout を再度起動します。

イベントをキャンセルするには、イベント リストからプロパティを設定解除するだけです。

キューに入れられたイベントを追加/削除したり、パラメーターを更新したりするためのメソッドをいくつか作成します。

それはすべてを1つのタイムアウトハンドラに減らします..

(ただのアイデア)

于 2010-11-18T03:12:02.450 に答える