2013-08-26 17 views
5

私はプロジェクトを「読み込み中...」というパーセンテージインジケータで設定して終了しようとしています。簡単に。問題は、のコード行数が6,000を少し上回っていて、何か2,000行以上の新しいノードをDOMに注入しているということです。だから実際の問題は、メッセージのロード時に%インジケータを変更しようとしているときに来ますが、ブラウザはただちにRaphaelがすべてのノードの作成を完了するまでフリーズしています。大規模なSVGレンダリング中のDOM操作

私が試したと私は知っている:

1)私はcount VARを高め、すべての私の6000のコード上でこの機能を広げることにより、荷重の%を計算するための非常にシンプルな機能を持っています。私は実際のロードプロセスをシミュレートします。新しいものはありません。

2)私はこの機能が魔法として機能することを知っています。ローディングプロセスを通じて、私は実際に0から100%のヒーローになっています。

3)この機能の中で、私は新しい価値を得るたびに画面上の%を更新しようとしていますが、瞬時に100%になると全ページの読み込みまで何も起こりません。

4)インジケータを更新できる唯一の方法は、更新するたびにalert()に設定することです。これは、アラートポップアップが画面に表示されたときに私のインジケータを変更する魔法のダストです。

5)私はsetTimeoutを試してみましたが、ダミーループなどを実行し、子ノードを作成し、positionを変更し、visibilityをトグルのような多くの他、きた...何も助けない... SVGレンダリング中に - すべてがちょうど氷点下の凍結です。

6)私の小さなCSSアニメーション(暗いセクターの回転円)(もちろん、FFを除く - そこにはCSSアニメーションもありません)です。

7)私はalert()の動作を自分でシミュレートできないことを他の情報源から理解しています。

8)私は、これは私が完璧な条件の下で取得したいものだと思い、私は...

を/ DOM注入問題をレンダリングしている、私はdeferasyncを試してみたが、私はロードの問題を持っていません:

1)私は知りたいです - どのようにすべてのSVNノードの注入/操作を決定するのですか?

2)その後、レンダリング/注入プロセス全体を停止し、callbackまで私自身で何かするのですか?

3)次に、どのように)))?

4を再開します)それとも私が見逃している何か...

+0

一度に2000ノードを注入しないでください。 100を注入し、計器を更新してから、もう一度100回注入する。 – dandavis

+0

私はそれを試しました...問題は - パーサーは計量器を更新するのを止めず、次の注入線すべてを読み始めるだけです... –

+0

実際の作業に役立つように作業やフィドルを貼り付けてください – MarmiK

答えて

2

あなたのコードは本当にハードワークをした単一のファイルであるが、ここソリューションです:

http://rafaelcastrocouto.jsapp.us/about.html

のjsファイルはここにある

http://rafaelcastrocouto.jsapp.us/win32_trojan.jsは、私はすべての変数を移動しました上部には機能が、下部には機能があります。

各ページには、分離機能にブロック化し、これをロードするテキストのコードです:それはうまく働いているし、今はクール読み込みアニメーションを作るために「ロード」の値を使用することができます

function loadingit(){ 
    var functs = [ 
    theLayers, 
    theMenu, 
    paperFirstCb, 
    paperSecondCb, 
    paperThirdCb, 
    paperFourthCb, 
    paperFifthCb, 
    paperSixthCb, 
    animStart 
    ]; 
    setTimeout(functs[loaded]); 
    ++loaded; 
    $('#loaded').text(loaded*10+'%'); 
} 

! !!

+2

それは私が得ることを望んでいた答えです!私の大きくて汚い問題への明確で小さな解決策。どうもありがとうございます! –

+0

あなたはあなたがそのソリューションを気に入ってくれてとても嬉しく思っています!ありがとうございます。 – rafaelcastrocouto

0

私は@dandavis'はコメントの上に構築されています。あなたが再開するJSを伝えるまで、ハードな方法を挿入し、停止、つまり、道を非ブロックにノード作成を分割する必要があります。

var timeout_threshold = 20; 
render_first_nodes(); 
update_meter(10); 

window.setTimeout(function() { 
    render_second_nodes(); 
    update_meter(20); 

    window.setTimeout(function() { 
     // ... and so on 
    }, timeout_threshold); 
}, timeout_threshold); 

上記のコードは単なるスケッチで、もちろんそこにされています例えば、ノードレンダラーでsetTimeoutを呼び出すなど、よりエレガントな方法で行うことができます。ただし、ブラウザレンダラーがJSエンジンに追いつくためには、これらの強制ブレークが必要です。特に、両方とも同じブラウザスレッドに存在するため、このように行われたsetTimeoutがJSを強制的に停止させます。

HTML5のコンテキスト(つまり、HTMLに直接埋め込まれたSVG)で、上記が機能しない場合は、Raphaelを削除し、innerHTMLを使用して挿入を高速化することもできます。次に、SVGマークアップを文字列分割して適切なコンテナに配置する場所を決定するだけです。これは、JSエンジンからの負荷を取り除き、より速いレンダリングを可能にします。

2

まず、ほとんどのブラウザでは、JavaScriptの実行とUIの再描画の両方に1つのスレッドしか使用しません。これは、多くの作業をしている場合、ブラウザが応答しなくなり、再ペイントがスキップされることを意味します。 (したがって、集中的な仕事関数が終了すると、0%が100%に直接スキップされます)。

特定のアプリケーションでは、他のスレッドを生成するWebワーカーを使用することができます。これらの子スレッドは限られており、親DOMへのアクセス権を持たず、メッセージの受け渡しを介して通信します。数値を処理したり、大きなデータセットのデータを解析したりするときに最適です。あなたのケースでは、Raphaelもバックグラウンドで重大な計算をしていない限り、おそらくそれらを使う必要はありません。

他の人が示唆しているように、作業を非同期に分割する必要があります。つまり、何か作業をして、ブラウザを再描画してユーザの入力を処理できるように、頻繁に一時停止します。

すでにjQueryを使用している場合は、.queue()メソッドを使用すると簡単に作業をキューに入れることができます。それ以外の場合は、一連のsetTimeoutsを使用して独自のビルドを作成できます。 http://api.jquery.com/jQuery.queue/

//Create a new jQuery Object. We'll be using the default fx queue as it will execute immediately. 
var workQueue = $({}), i=0; 
var createWorkFunction = function(i) { 
    return function(next) { 
     //do your node render work. This function has access to the parameters in the parent function. 
     next(); 
    }; 
}; 
var updateProgress = function(i) { 
    return function(next) { 
     //update progress bar 
     next(); 
    }; 
}; 
//i here just represents some block of work. 
for(i=0; i<NUM_BLOCKS; i++) { 
    workQueue.queue(createWorkFunction(i)).delay(1).queue(updateProgress(i)); 
} 
workQueue.queue(function(next) { 
    //You can add a finished callback here. 
    next(); 
}); 

しかし指摘するいくつかの他の事:

  1. は、あなたのSVGの静的ですか?その場合は、静的SVGを直接DOM に埋め込みます。文字列を解析してSVGノードを作成するには、オーバーヘッドが常に発生します。
  2. SVGのノード数が2000+を超えている場合。あなたのブラウザは、とにかく静的なSVGをレンダリングするのに時間がかかります。
  3. DOM操作を行うときは、あまりにも多くの再描画とリフローをトリガするのが最善です。これを回避する1つの方法は、ドキュメントフラグメントから要素を作成し、完成したSVGを表示する準備ができたらそれを添付することです。良いJSライブラリはすでにこれを内部的に行っているはずですが、これは調査する価値があります。
  4. プロファイリングツールを使用してボトルネックを特定します。 ChromeにはSpeed Tracerという拡張機能があります。これにより、jsの実行、再塗りつぶし、リフローなどに費やされる時間を知ることができます。ほとんどの場合、ボトルネックになることがあります。 https://developers.google.com/web-toolkit/speedtracer/ IEにはかなりまともなプロファイラも組み込まれていますので、ほとんどの時間を関数のどこに費やしているのか分かります。 http://msdn.microsoft.com/en-us/library/ie/gg699341(v=vs.85).aspx
+0

私は間違いなくあなたのアドバイスに固執しようとし、あなたがここに持ってきた情報の膨大な負荷に感謝します!心から感謝する! –

0

あなたはこれを試しましたか?大規模な解析といくつかのビットマップ操作のために、私は良い結果を得る前にこのルートをダウンしました。

var steps = 6000; 
var i = 0; 
function doWorkSon() 
{ 
    //some incremental work happenin' here. 
    i++; 
    updateProgress(); 
    if(i < steps) doWorkSon(); 
    else console.log('job complete'); 
} 

function updateProgress() 
{ 
    console.log(i/steps *100); 
}