6

以下のスクリプトを使用すると、ビジュアルとパフォーマンスに深刻な問題が発生します。最大の問題は、オブジェクトのアニメーションが非常にぎくしゃくしていることです。IE9 ではほとんど不自由ですが、Firefox ではますます煩わしくなります。

最近までかなり高速でしたが、複雑さが速度を落としているのではないかと心配しています。奇妙なことに、Sunspider ベンチマークは、Firefox よりも IE9 インスタンスの方が高速に実行されます。

スクリプト (より大きなコレクションのスニペットです ***):

  1. ユーザーのゲーム進行状況の HTML5 セッション ストレージ ログをチェックします。
  2. ステージに応じて、crSplineを使用して 2 点間のオブジェクトをアニメーション化します。
  3. scrollLeft などを介して、ブラウザー ウィンドウが大きなキャンバス全体でオブジェクトをたどるようにします。
  4. 最後に、 colorboxを介してポップアップ ウィンドウを読み込みます。
  5. このボックスを閉じると、それに応じてユーザー進行ログが増加し、オブジェクトが再び移動します。

コードに加えることができる明白な速度の改善はありますか? かなりの繰り返しがありますが、どうすればそれを減らすことができますか? 私が見逃している無限ループが実行されていますか? JS のスロー ポイントをプロファイリングするために使用できるソフトウェアはありますか?

*** (他の JS ファイルや HTML を提供することはできませんが、このスクリプトが問題であると特定しました)


更新: かなり多くのテストの後、scrollLeft を介してウィンドウ内のオブジェクトを追跡するステップ アニメーション機能が、ぎくしゃくしたアニメーションを引き起こしているようです。それを取り除くと、物事はかなり改善されます。

ただし、これは実行可能な長期的な解決策ではありません。簡単な解決策は、完了時に follow 関数を呼び出すことですが、これは、特にオブジェクトがより長い距離を移動する場合に、エンド ユーザーのエクスペリエンスが大幅に低下します。

では、ステップ関数を変更して、「より遅く」/より効率的に実行するにはどうすればよいでしょうか? ジャーキネスは、利用可能なすべてのリソースを使用してミリ秒ごとにオブジェクトを追跡することが原因であると推測しています。

(function ($) {

  sessionStorage.gameMainStage = 0 

  moveShip =  function() {

    switch (sessionStorage.gameMainStage)

{
  case '1':
    $("#object").animate(
      { crSpline: $.crSpline.buildSequence([[715, 425], [582, 524], [556, 646], [722, 688], [963, 629], [1143, 467]]) },{
      duration: 10000,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
          },
          complete: function() {
            $.colorbox({href:"dialog-1.html", width:"737px", height:"474px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }
      }
    );
    break;

  case '2':
    $("#object").animate(
      { crSpline: $.crSpline.buildSequence([[1143, 467], [1343, 667], [1443, 367],  [1243, 167], [1499, 285]]) },
        {
          duration: 5000,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
          },
          complete: function() {
            $.colorbox({href:"dialog-2", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }

        }
    );
    break;

  case '3':
    $("#object").animate(
      { crSpline: $.crSpline.buildSequence([[1499, 285], [1922, 423]]) },
        {
          duration: 5000,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
          },
          complete: function() {
            $.colorbox({href:"dialog-3.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }

        }
    );
    break;  

  case '4':
    $("#object").animate(
      { crSpline: $.crSpline.buildSequence([[1922, 423], [2216, 578]]) },{
        duration: 5000,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
            }, 

          complete: function() {
            $.colorbox({href:"game-1.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }
        }
    );
    break;

  case '5':
    $("#object").animate(
      { crSpline: $.crSpline.buildSequence([[2216, 578], [2769, 904]]) },{
      duration: 5000,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
          }, 

          complete: function() {
            $.colorbox({href:"dialog-4.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }
      }
    );
    break;

  case '6':
    $("#object").animate(
      { crSpline: $.crSpline.buildSequence([[2769, 904], [3263, 903]]) },{
      duration: 5000,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
          }, 

          complete: function() {
            $.colorbox({href:"dialog-5.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }
      }
    );
    break;

  case '7':
    $.colorbox({href:"game-2.html", width:"500px", height:"600px", iframe: true, overlayClose: false, escKey: false, close: ""});
  break;

  case '8':
    $.colorbox({href:"dialog-6.html", width:"737px", height:"567px", iframe: true, overlayClose: false, escKey: false, close: ""});
  break;

  case '9':
    $("#object").animate(
      { crSpline: $.crSpline.buildSequence([[3263, 903], [4141, 820]]) },{
      duration: 5000,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
          }, 

          complete: function() {
            $.colorbox({href:"dialog-7.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }
      }
    );
    break;

  case '10':
    $("#object").animate(
      { crSpline: $.crSpline.buildSequence([[4141, 820], [4568, 949], [4447, 1175]]) },{
      duration: 5000,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
          }, 

          complete: function() {
            $.colorbox({href:"dialog-8.html", width:"737px", height:"434px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }
      }
    );
    break;

  case '11':
    $.colorbox({href:"dialog-9.html", width:"737px", height:"567px", iframe: true, overlayClose: false, escKey: false, close: ""});
  break;

  case '12':
    $("#object").animate(
      { crSpline: $.crSpline.buildSequence([[4447, 1175], [4701, 1124], [4816, 822]]) },{
      duration: 5000,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
          }, 

          complete: function() {
            $.colorbox({href:"dialog-10.html", width:"900px", height:"687px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }
      }
    );
    break;
}

};

})(jQuery);
4

5 に答える 5

11

残念ながら、あなたが使用しているライブラリは古すぎて、素晴らしいパフォーマンスを期待できません.

あなたのコードには何も問題はありません (ただし、各スイッチ ケースの config 引数を使用して関数を使用することはできましたが、それはパフォーマンスに大きな影響を与えないリファクタリングの問題です)。

CrSpline は、左と上の CSS プロパティを使用します。

ハードウェア アクセラレーションを利用する CSS 2d 変換を調べるとよいでしょう。

-webkit/moz/ms-transform: translateX(-1000px) translateY(200px) の代わりに使用left: -1000px; top: 200px;

crspline ライブラリの一部のコードをその方向に簡単に書き直すことができると思います。

より最新の「スプライン」ライブラリを探すこともできます。

別のポイント: crSpline は requestAnimationFrame 機能を使用していないようです。JQuery のanimateメソッドもそうではありません。TweenLite/TweenMax ライブラリをご覧になることをお勧めします: http://www.greensock.com/v12/

あなたの仕事に乾杯!

于 2012-10-21T19:45:54.887 に答える
5

window.resizeとwindow.scrollにフックしたシングルページアプリケーションでこの問題が発生しました。IEでは他のブラウザよりもはるかに遅いようでした。

私が最初に気付いたのは、IE(具体的にはバージョン8)では、window.scrollまたは.resizeにアタッチされたコールバックが、ウィンドウのサイズ変更(またはスクロール)中にChromeまたはFFよりも何倍も起動するように見えたことです。そのため、添付されたコールバックはChromeの何倍も呼び出され、相対的なコストが増加します。

これらのコールバック内で行われていることを最小限に抑えることで問題を解決することができました。主なメリットは、jQueryセレクターを取り除くことでした。したがって、あなたの場合、たとえば、コールバック関数にvar mover = $('#object')があります。イベントが発生するたびに、IEはオブジェクトを見つけて取得し、jQueryでラップしようとします。これは、コールバックしてから、キャッシュされたオブジェクトを使用します。私たちの場合、それはマグニチュードオーダーでパフォーマンスを改善し、パフォーマンスの問題が発生しなかったとしても(それは不必要に繰り返された操作でした)、それは良いことのように思えました。

したがって、たとえばケース8の場合、次のようになります。

 case '10':{
    //caching myObject once and then use it afterwards
    var myObject = $("#object"),
        $window = $(window);

    myObject.animate(
      {
      crSpline: $.crSpline.buildSequence([[4141, 820], [4568, 949], [4447, 1175]]) },
      {
      duration: 5000,
          step: function() {
            var mover = myObject, //no need to refetch the object               
            posX = mover.position().left;
            posY = mover.position().top;

            $window.scrollLeft(posX - $window.width() / 2)
            .scrollTop(posY - $window.height() / 2);
          }, 

          complete: function() {
            $.colorbox({href:"dialog-8.html", width:"737px", height:"434px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }
      }
    );
}

ps:さらに、アプリケーションのセマンティクスがわかりませんが、posXとposYは常に元のキャッシュされたオブジェクトを参照している可能性があるため、独自のロジックを追加して追跡する必要がある場合がありますが、すべての場合で、前述の手順を実行してくださいセレクターのコストが問題の原因であることを確認するため(私の場合のように)。

于 2012-10-26T21:10:52.253 に答える
2

まず、アニメーション用の関数を作成するコードを最適化する必要があります (テストされていませんが、動作するはずです)。

function animateMyObjet(duration,sequence,callback)
{
    $("#object").animate(
    {   crSpline: $.crSpline.buildSequence(sequence),
        {
          duration: duration,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
          },
          complete: function() {
            callback();
        }
    }
}

次のようにコードで呼び出されます:

switch (sessionStorage.gameMainStage)
{
  case '1': animateMyObjet(10000,[[715, 425], [582, 524], [556, 646], [722, 688], [963, 629], [1143, 467]],                                                                                  
function() {
$.colorbox({href:"dialog-1.html", width:"737px", height:"474px", iframe: true, overlayClose: false, escKey: false, close: ""});
        break;

case '2' : ...

}

次に、Web ページの要素数が IE9 のパフォーマンスに影響を与えていることを数週間前に発見しました。スクロール可能なコンテナのために要素を非表示にするなど、必要のないすべての要素を非表示にしてください。

画面の表示要素の数がアニメーションのパフォーマンスに影響を与えることがあります。テストのために、ブラウザ ウィンドウのサイズを小さくして、アニメーションを再生してみてください。アニメーションがよりスムーズになると確信しています。

これらのアドバイスがお役に立てば幸いです。問題が解決したら、最終的な解決策を公開することを忘れないでください!

最後に、IE9 のパフォーマンスの問題に関する潜在的な関連トピックを確認してください: IE9 : Web サイトの CPU 使用率が常に小さい

于 2012-10-21T19:50:11.910 に答える
0

私の考えでは、イベント ハンドラーがあまりにも頻繁に呼び出されている場合は、タイムアウトが現在設定されておらず、タイムアウト関数に動きの肉がある場合、イベント ハンドラーにタイムアウト (たとえば 10 ミリ秒) を設定させるだけです。

于 2012-10-27T22:09:06.547 に答える