UNPKG

@giro3d/giro3d

Version:

A JS/WebGL framework for 3D geospatial data visualization

111 lines (108 loc) 2.89 kB
/* * Copyright (c) 2015-2018, IGN France. * Copyright (c) 2018-2026, Giro3D team. * SPDX-License-Identifier: MIT */ import { CanvasTexture, MathUtils, Texture } from 'three'; import EmptyTexture from '../renderer/EmptyTexture'; import Fetcher from '../utils/Fetcher'; import ImageSource, { ImageResult } from './ImageSource'; /** * Options for the {@link StaticImageSource} constructor. */ /** * An {@link ImageSource} that displays a single, static image. * * The image must be either a PNG, JPG or WebP file, whose dimensions are not greater * than the maximal texture size allowed by WebGL on this browser. */ export default class StaticImageSource extends ImageSource { isStaticImageSource = true; type = 'StaticImageSource'; _id = MathUtils.generateUUID(); /** * Create a {@link StaticImageSource}. * @param options - The options. */ constructor(options) { super({ colorSpace: 'srgb', flipY: typeof options.source === 'string' ? false : options.flipY ?? true, is8bit: true }); if (options.source == null) { throw new Error('invalid source'); } if (options.extent == null) { throw new Error('invalid extent'); } this._extent = options.extent; this._source = options.source; } getExtent() { return this._extent; } getCrs() { return this._extent.crs; } async fetchTexture(url) { // We directly flip the texture during decoding, which is why we don't need to flip it in the layer itself. return Fetcher.texture(url, { flipY: true, priority: this.priority }).then(texture => { this.dispatchEvent({ type: 'loaded' }); return texture; }).catch(error => { console.error(error); this.dispatchEvent({ type: 'error', error }); return new EmptyTexture(); }); } async loadImageOnce() { let texture; if (typeof this._source === 'string') { texture = await this.fetchTexture(this._source); } else if (this._source instanceof HTMLCanvasElement) { texture = new CanvasTexture(this._source); } else if (this._source instanceof HTMLImageElement) { texture = new Texture(this._source); } else { texture = this._source; } return new ImageResult({ id: this._id, texture, extent: this._extent }); } adjustExtentAndPixelSize(requestExtent, requestWidth, requestHeight) { return { extent: requestExtent, width: requestWidth, height: requestHeight }; } update() { this._promise = undefined; super.update(); } async loadImage() { if (this._promise == null) { this._promise = this.loadImageOnce(); } return this._promise; } getImages() { const response = { id: this._id, request: this.loadImage.bind(this) }; return [response]; } }