序文プログラムを作成するときに、読み込みの進行状況やアップロードの進行状況など、進行状況を表示する必要に迫られることがよくあります。 質問私は WebGL アプリケーションを作成しており、アプリケーションのプリロード フェーズ中にロードの進行状況を計算する必要があります。 +-------------------------------------------------------------+ | | | リソース | | | | +----------+ +-----------------+ +-----------------+ | | | スクリプト1 | | モデル1 | | モデル2 | | | +----------+ | | | | | | | -------------+ | | -------------+ | | | +----------+ | |model1.json | | | |model2.json | | | | | スクリプト2 | | +-------------+ | | +-------------+ | | | +----------+ | | | | | | | +-------------+ | | +-------------+ | | | +----------+ | | 素材1 | | | | 素材1 | | | | | テクスチャ1 | | | +--------+ | | | | +--------+ | | | | +----------+ | | |テクスチャ1| | | | | |テクスチャ1| | | | | | | +--------+ | | | | +--------+ | | | | +----------+ | | +--------+ | | | | +--------+ | | | | | テクスチャ2 | | | |テクスチャ2| | | | | |テクスチャ2| | | | | +----------+ | | +--------+ | | | | +--------+ | | | | | +-------------+ | | +-------------+ | | | | | | | | | | +-------------+ | | +-------------+ | | | | | マテリアル2 | | | | マテリアル2 | | | | | +-------------+ | | +-------------+ | | | +-----------------+ +-----------------+ | | | +-------------------------------------------------------------+ ここで前提となるのは、リソースをロードするときに、ロードが完了したと見なされる前に、リソースとそれが参照するリソースがすべてロードされていることを確認する必要があるということです。 クラスアセット{ ロード(onProgress) { 新しいPromise((resolve) => {を返す if (typeof onProgress !== 'function') { onProgress = (_p) => { }; } loadedCount = 0 とします。 let totalCount = 10; // 注意: デモ用です onLoaded = () => { ロードされたカウント++; onProgress(読み込まれたカウント / 合計継続時間); 読み込まれたカウントが合計カウントの場合、解決します。 }; 約束.すべて( this.refAssets.map(asset => asset.load().then(onLoaded)) ); }); } } このインターフェースができたので、loadedCount と totalCount のグローバルメンテナンスという形式を引き続き使用すると、扱いが非常に面倒になります。 原理基本的な考え方は分割統治です。大きなタスクを複数の小さなタスクに分割し、すべての小さなタスクの進行状況を個別に計算し、最後にすべての小さなタスクの進行状況を結合して全体の進行状況を取得します。 +--------------------------------------------------------------------+ | | | | | 総進捗状況 | | | | +---------+----------+-----------+----------+---------+---------+ | | | スクリプト1 | スクリプト2 | テクスチャ1 | テクスチャ2 | モデル1 | モデル2 | | | | (0~1) | (0~1) | (0~1) | (0~1) | (0~1) | (0~1) | | | +---------+----------+-----------+----------+---------+---------+ | | | | モデル1 | | +-------------+------------------------+-----------+ | | | model1.json | マテリアル1 | マテリアル2 | | | | (0~1) | (0~1) | (0~1) | | | +------------------------+------------------------+ | | | テクスチャ1 | テクスチャ2 | | | | (0~1) | (0~1) | | | +----------+-------------+ | | | | モデル2 | | +-------------+------------------------+-----------+ | | | model2.json | マテリアル1 | マテリアル2 | | | | (0~1) | (0~1) | (0~1) | | | +------------------------+------------------------+ | | | テクスチャ1 | テクスチャ2 | | | | (0~1) | (0~1) | | | +----------+-------------+ | | | +--------------------------------------------------------------------+ この原則に基づいて、すべてのリソースの現在の読み込み進行状況をリストに保存し、onProgress がトリガーされるたびにマージ操作を実行して全体の進行状況を計算することで、進行状況が実装されます。 var 進行 = [ 0, // スクリプト1, 0, // スクリプト2, 0, // テクスチャ1, 0, // テクスチャ2, 0, // モデル1, 0, // モデル2 ]; 関数 onProgress(p) { // TODO: progresses[??] = p; progresses.reduce((a, b) => a + b, 0) / progresses.length を返します。 } しかし、ここには難しさがあります。onProgress コールバックがトリガーされたとき、リスト内のどの項目を更新する必要があるかをどのように知るのでしょうか? var 進捗 = []; 関数add(){ 進行します。push(0); var インデックス = progresses.length - 1; 関数onProgress(p)を返す{ progresses[インデックス] = p; 減らす(); }; } 関数reduce() { progresses.reduce((a, b) => a + b, 0) / progresses.length を返します。 } クロージャを使用してリソースのインデックスを保持します。onProgress がトリガーされると、リスト内の対応する項目の進行状況をインデックスに従って更新できます。正しい進行状況は最終マージ時に計算できます。 テスト次のコードを使用して、読み込みプロセス全体をシミュレートできます。 クラスアセット{ コンストラクター(totalCount) { this.loadedCount = 0; this.totalCount = 合計カウント; this.timerId = -1; } ロード(onProgress) { if (typeof onProgress !== 'function') { onProgress = (_p) => { }; } 新しいPromise((resolve) => {を返す this.timerId = setInterval(() => { this.loadedCount++; onProgress(this.loadedCount / this.totalCount); (this.loadedCount === this.totalCount)の場合{ タイマーIDをクリアします。 解決する(); } }, 1000); }); } } クラス Progress { コンストラクター(onProgress) { onProgress は、次の式で定義されます。 this._list = []; } 追加() { this._list.push(0); 定数インデックス = this._list.length - 1; 戻り値 (p) => { this._list[インデックス] = p; これをreduce()します。 }; } 減らす() { 定数 p = Math.min(1, this._list.reduce((a, b) => a + b, 0) / this._list.length); this.onProgress(p); } } const p = 新しい Progress(console.log); 定数asset1 = 新しいアセット(1); 定数asset2 = 新しいアセット(2); 定数asset3 = 新しいアセット(3); 定数asset4 = 新しいアセット(4); 定数asset5 = 新しいアセット(5); Promise.all([ アセット1.load(p.add())、 アセット2.load(p.add())、 アセット3.load(p.add())、 アセット4.load(p.add())、 アセット5.load(p.add())、 ]).then(() => console.log('すべてのリソースが読み込まれました')); /** 出力 Promise { <state>: "pending" } 0.2 0.3 0.366666666666666664 0.416666666666666663 0.456666666666666667 0.55666666666666668 0.6233333333333333 0.6733333333333333 0.7133333333333333 0.78 0.83000000000000001 0.8699999999999999 0.9199999999999999 0.96 1 すべてのリソースが読み込まれました */ この方法の利点は、loadedCount と totalCount のグローバル管理を回避し、この部分の作業をリソースの内部管理に戻すことができることです。必要なのは、大きなタスクをマージして計算することだけです。 欠点も明らかであり、onProgress インターフェースを統一する必要があります。既存のプロジェクトを進めるのは非常に難しいため、新規プロジェクトや小規模プロジェクトに適しています。 以上がJavaScript進捗管理の詳細です。JavaScript進捗管理の詳細については、123WORDPRESS.COMの他の関連記事にも注目してください! 以下もご興味があるかもしれません:
|
<<: Windows 10 での MySQL 5.7.21 winx64 のインストールと設定方法のグラフィック チュートリアル
お使いのコンピュータが Mac の場合、homebrew を使用して MySQL をインストールする...
この記事では、Jingdongの虫眼鏡効果を実現するためのJavaScriptの具体的なコードを紹介...
コンパイル後にAngularプロジェクトをNginxにデプロイする方法をオンラインで検索すると、ほと...
1. 設置前の清掃 rpm -qa | grep jdk rpm -qa | grep gcj yu...
1. ログセグメンテーションのためのLog4j 1) log4j-1.2.17.jar、tomcat...
フロントエンド ページの需要が増加し続けるにつれて、一部のシーンではグラデーションの背景要素が必要に...
XML価格照会のクエリデータにはリストが含まれているため、コレクションが必要です <結果マップ...
問題の説明MySQL が正常に起動しました。以下に示すように、 ps -ef |grep mysql...
目次参照と反応参照反応的RefとReactiveの違いshallowRef と shallowRea...
docker-compose.ymlを作成し、次の内容を入力します。 バージョン: '3...
目次1. MySQL で現在の時刻を表現するにはどうすればよいでしょうか? 2. TIMESTAMP...
Nginx Rewriteの使用シナリオ1. URL アドレスジャンプ。たとえば、ユーザーが pm....
目次1. ローカルストレージを構築する2. npmパッケージを作成し、プライベートリポジトリにアップ...
目次概要1. フロントエンドとバックエンドの分離とWeb APIの優先ルート設計2. Axiosネッ...
MySQL 8.0.13 にはデフォルトでデータ フォルダがあります。このフォルダを削除する必要があ...