import Resource, { URLResource } from "./Resource"; /** * @summary ローダークラス * @memberof mapray */ class Loader { /** * @param {mapray.Scene} scene 読み込み先のシーン * @param {mapray.Resource} resource * @param {object} [options={}] * @param {object} [options.onLoad] 全ての読み込み完了時に呼ばれる * @param {mapray.Loader.EntityCallback} [options.onEntity] エンティティが読み込まれるたびに呼ばれる */ constructor( scene, resource, options={} ) { this._scene = scene; if (!(resource instanceof Resource)) { throw new Error("Unsupported Resource Type: " + resource); } this._resource = resource; this._status = Loader.Status.NOT_LOADED; this._onLoad = options.onLoad || defaultOnLoadCallback; this._onEntity = options.onEntity || defaultOnEntityCallback; } /** * @summary 読み込み先のシーン * @type {mapray.Scene} * @readonly */ get scene() { return this._scene; } /** * @summary シーンリソース * @type {string} * @readonly */ get resource() { return this._resource; } /** * ローダー読み込みの状態 * @readonly */ get status() { return this._status; } /** * @private */ _setStatus( status ) { this._status = status; } /** * @summary 読み込みを実行します。 * @returns {Promise} */ load() { if ( this.status !== Loader.Status.NOT_LOADED ) { return Promise.reject( new Error( "Illegal Status: " + this.status ) ); } return ( Promise.resolve() .then( () => { this._setStatus( Loader.Status.LOADING ); this.scene.addLoader( this ); return this._load(); } ) .catch( error => { // JSON データの取得に失敗 (キャンセルによる失敗の可能性あり) console.log( error ); this._scene.removeLoader( this ); this._onLoad( this, false ); if ( this._status !== Loader.Status.CANCELED ) { this._setStatus( Loader.Status.ABORTED ); } throw error; } ) .then( value => { this._scene.removeLoader( this ); if ( this._status === Loader.Status.CANCELED ) { this._onLoad( this, false ); throw new Error( "canceled" ); } else { this._setStatus( Loader.Status.LOADED ); this._onLoad( this, true ); return value; } } ) ); } /** * @summary 読み込み処理の実態。継承クラスによって実装される。 * @private */ _load() { throw new Error( "_load() is not implemented in " + this.constructor.name ); } /** * @summary 読み込みの取り消し * @desc * <p>終了コールバック関数は isSuccess == false で呼び出される。</p> */ cancel() { if ( this._status === Loader.Status.LOADING || this._status === Loader.Status.LOADED ) { this._setStatus( Loader.Status.CANCELED ); this._resource.cancel(); this._cancel(); // this._scene.removeLoader( this ); // this._onLoad( this, false ); } } /** * @summary キャンセル時に行う処理。継承クラスによって実装される。 * @private */ _cancel() { } /** * 取り消し状態のとき例外を投げる * @private */ _check_cancel() { if ( this.status === Loader.Status.CANCELED ) { throw new Error( "canceled" ); } } } /** * @summary Entity読み込みコールバック * @callback EntityCallback * @desc * <p>読み込み処理の中でEntityが生成される際に呼ばれる。 * 一度の読み込み(load()呼び出し)において複数のエンティティが生成される場合は、エンティティが生成されるたびに呼ばれる。 * この関数をLoaderに指定する場合は、callback処理の中でEntityをsceneへ追加する必要がある。 * geojsonのように、要素ごとにプロパティを含められるような場合は、propにより値にアクセスする。 * </p> * * @param {mapray.Loader} loader Loader * @param {mapray.Entity} entity 読み込まれたEntity * @param {object} prop エンティティ生成の元となるオブジェクト * * @example * const loader = new mapray.SceneLoader( viewer.scene, resource, { * onEntity: ( loader, entity, prop ) => { * entity.setScale( [ 2, 2, 2 ] ); * loader.scene.addEntity( entity ); * } * } ); * loader.load(); * * @memberof mapray.Loader */ Loader.Status = { NOT_LOADED : "Not Loaded", LOADING : "Loading", LOADED : "Loaded", CANCELED : "Canceled", ERROR : "ERROR" }; function defaultOnLoadCallback( loader, isSuccess ) { } function defaultOnEntityCallback( loader, entity ) { loader.scene.addEntity( entity ); } /** * @summary リソース要求変換関数 * @callback TransformCallback * @desc * <p>リソースのリクエスト時に URL などを変換する関数の型である。</p> * * @param {string} url 変換前のリソース URL * @param {mapray.Resource.ResourceType} type リソースの種類 * @return {mapray.Loader.TransformResult} 変換結果を表すオブジェクト * * @example * function( url, type ) { * return { * url: url, * credentials: mapray.CredentialMode.SAME_ORIGIN, * headers: { * 'Header-Name': 'Header-Value' * } * }; * } * * @memberof mapray.Loader */ /** * @summary リソース要求変換関数の変換結果 * @typedef {object} TransformResult * @desc * <p>関数型 {@link mapray.Loader.TransformCallback} の戻り値のオブジェクト構造である。</p> * @property {string} url 変換後のリソース URL * @property {mapray.CredentialMode} [credentials=SAME_ORIGIN] クレデンシャルモード * @property {object} [headers={}] リクエストに追加するヘッダーの辞書 (キーがヘッダー名、値がヘッダー値) * @memberof mapray.Loader */ export default Loader;