6

JavaScript の非常に集中的な期間中に、かなり重い 3D 配列が構築されて埋められるローディング バーを作成しようとしています。この読み込みバーは、ユーザーがボタンをクリックするまで空のままにしておく必要があります。

使用しているかどうかに関係なく、フリーズが発生します-webkit-transition(このアプリはクロム専用である可能性があり、私の場合、クロスブラウザーは必要ありません)。

シンプルさを求めて、このようにバーを構築しました...

<div id="loader">
    <div id="thumb">
    </div>
</div>

...そして、メインforループのさまざまな段階でそのバーをインクリメントしようとしました:

for(i = 0; i < 5 ; i++){
    document.getElementById('thumb').style.width = i*25 + '%';
    //More Code
}

問題は、JavaScript が終了するまですべてがフリーズすることです。Stack Overflow で同様の質問を見つけ、JavaScript の計算中に CSS アニメーションを使用し、コメントで次のことを見つけて検討および/または試しました。

  • ウェブワーカー

    私のスクリプトは、このサイトによると機能しない関数を含むオブジェクトとコンストラクターで配列を埋めているため、機能するとは思わないでください

  • jQuery

    オプションではありません。アプリで外部ライブラリを使用できません。いずれにせよ、読み込みバーのためだけにライブラリ全体をインポートするのはやり過ぎのようです...

  • キーフレーム

    これは有望で試してみましたが、最終的にはフリーズするので、喜びはありません

  • timeOut()s

    と思ったのですが、ローディングバーの目的はフラストレーションを軽減することなので、待ち時間を増やすのは逆効果に思えます

スムーズでなくても、この段階でバーを少しでも増やしていただければ幸いです。これは私だけではない問題であると確信しています。誰かが興味深い解決策を持っているのではないでしょうか?

PS: 参照されている質問に追加するのではなく、新しい質問として投稿しています。これは、特に JavaScript (jQuery ではなく) のヘルプを求めており、幅のトランジション (!=アニメーション) を使用して取得できる場合を希望するためです。 .

4

2 に答える 2

5

一部の人々は、タイムアウトを使用する必要があるとすでに述べています。これは適切なアプローチです。これにより、ブラウザが「呼吸」して進行状況バーをタスクの途中でレンダリングする時間が与えられます。

非同期で動作するようにコードを分割する必要があります。現在、次のようなものがあるとします。

function doAllTheWork() {
  for(var i = 0; i < reallyBigNumberOfIterations; i++) {
    processorIntensiveTask(i);
  }
}

次に、それを次のように変換する必要があります。

var i = 0;
function doSomeWork() {
  var startTime = Date.now();
  while(i < reallyBigNumberOfIterations && (Date.now() - startTime) < 30) {
    processorIntensiveTask(i);
    i++;
  }

  if(i < reallyBigNumberOfIterations) {
    // Here you update the progress bar
    incrementBar(i / reallyBigNumberOfIterations);

    // Schedule a timeout to continue working on the heavy task
    setTimeout(doSomeWork, 50);
  }
  else {
    taskFinished();
  }
}

function incrementBar(fraction) {
  console.log(Math.round(fraction * 100) + ' percent done');
}

function taskFinished() { console.log('Done!'); }

doSomeWork();

式に注意してください(Date.now() - startTime) < 30。これは、ループが 30 ミリ秒のスパンでできる限りの処理を行うことを意味します。この数値を大きくすることはできますが、100 ミリ秒 (基本的には 1 秒あたり 10 フレーム) を超えると、ユーザーの観点からは遅く感じ始めます。

同期バージョンとは対照的に、このアプローチを使用すると、全体的なタスクに多少時間がかかることは事実かもしれません。ただし、ユーザーの経験からすると、何も起こっていないように見える間に無期限に待機するよりも、何かが発生しているという兆候がある方が適切です (後者の待機時間が短くても)。

于 2012-11-19T21:12:26.397 に答える
1

さらに単純化して関数を作成しようとしたことがありますか?

擬似:

Function increment_bar(amount = 10)
{
 document.getElementById('thumb').style.width = i*amount + '%';
}

次に、処理作業を行っている場所から x 秒ごとに、または処理の特定のポイントに達するたびにその関数を呼び出すだけです (10 ~ 20% の完了としましょう?)

擬似:

{
    Doing_work_here;
    increment_bar(25);
    LOOP
}
于 2012-11-19T20:47:40.107 に答える