序文プログラムを作成するときに、読み込みの進行状況やアップロードの進行状況など、進行状況を表示する必要に迫られることがよくあります。 質問私は 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 のインストールと設定方法のグラフィック チュートリアル
Navicatをインストールした後次のエラーが発生する場合があります: Client does no...
始める前に、これから紹介する JOIN タイプを示すために 2 つのテーブルを作成します。テーブルを...
目次セマフォNginx ホットデプロイメント上記のブログ投稿に従ってください。ファイアウォールをオフ...
序文最近、弊社では mbp の設定をしており、ssh を使うことが多くなりました。複雑なコマンドを書...
1. 問題の説明: MysqlERROR1698 (28000) の解決方法、新しくインストールされ...
目次1. ElementUIで基本的なスタイルを構築する2. [送信]ボタンをクリックして、アカウン...
目次1. vue-cli デフォルト プロジェクトを作成する (babel のみを含む) 2. 作成...
目次1. プロトタイプとプロトタイプチェーンの平等関係を理解する2: プロトタイプとプロトタイプ チ...
目次1. 概要2. dockerを使用してTomcatをデプロイし、Skywalkingに接続する要...
ローカルの MySQL バージョンが比較的低いため、最近 MySQL のバージョンをアップグレードす...
オリジナルリンク: https://vien.tech/article/138序文私は、マークダウン...
1. まず本文にulタグを追加します <!-- 順序なしリスト --> <ul i...
夜にMACの電源を入れたところ、突然ルートアカウントがMySQLに正常にログインできなくなったため、...
この例では、jQuery を使用してマウス ドラッグ イメージ機能を実装します。まず、ラッパーを設定...
序文ヒストグラムは、RDBMS によって提供される基本的な統計情報です。最も一般的に使用されるのは、...