Allow maps to be configured with a promise for view props
This commit is contained in:
@@ -137,7 +137,7 @@ import {removeNode} from './dom.js';
|
||||
* element itself or the `id` of the element. If not specified at construction
|
||||
* time, {@link module:ol/Map~Map#setTarget} must be called for the map to be
|
||||
* rendered. If passed by element, the container can be in a secondary document.
|
||||
* @property {View} [view] The map's view. No layer sources will be
|
||||
* @property {View|Promise<import("./View.js").ViewOptions>} [view] The map's view. No layer sources will be
|
||||
* fetched unless this is specified at construction time or through
|
||||
* {@link module:ol/Map~Map#setView}.
|
||||
*/
|
||||
@@ -388,6 +388,13 @@ class PluggableMap extends BaseObject {
|
||||
// is "defined" already.
|
||||
this.setProperties(optionsInternal.values);
|
||||
|
||||
const map = this;
|
||||
if (options.view && !(options.view instanceof View)) {
|
||||
options.view.then(function (viewOptions) {
|
||||
map.setView(new View(viewOptions));
|
||||
});
|
||||
}
|
||||
|
||||
this.controls.addEventListener(
|
||||
CollectionEventType.ADD,
|
||||
/**
|
||||
@@ -1496,12 +1503,24 @@ class PluggableMap extends BaseObject {
|
||||
|
||||
/**
|
||||
* Set the view for this map.
|
||||
* @param {View} view The view that controls this map.
|
||||
* @param {View|Promise<import("./View.js").ViewOptions>} view The view that controls this map.
|
||||
* It is also possible to pass a promise that resolves to options for constructing a view. This
|
||||
* alternative allows view properties to be resolved by sources or other components that load
|
||||
* view-related metadata.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setView(view) {
|
||||
this.set(MapProperty.VIEW, view);
|
||||
if (!view || view instanceof View) {
|
||||
this.set(MapProperty.VIEW, view);
|
||||
return;
|
||||
}
|
||||
this.set(MapProperty.VIEW, new View());
|
||||
|
||||
const map = this;
|
||||
view.then(function (viewOptions) {
|
||||
map.setView(new View(viewOptions));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1600,7 +1619,7 @@ function createOptionsInternal(options) {
|
||||
values[MapProperty.TARGET] = options.target;
|
||||
|
||||
values[MapProperty.VIEW] =
|
||||
options.view !== undefined ? options.view : new View();
|
||||
options.view instanceof View ? options.view : new View();
|
||||
|
||||
let controls;
|
||||
if (options.controls !== undefined) {
|
||||
|
||||
@@ -5,10 +5,15 @@ import DataTile from './DataTile.js';
|
||||
import State from './State.js';
|
||||
import TileGrid from '../tilegrid/TileGrid.js';
|
||||
import {Pool, fromUrl as tiffFromUrl, fromUrls as tiffFromUrls} from 'geotiff';
|
||||
import {Projection, get as getCachedProjection} from '../proj.js';
|
||||
import {
|
||||
Projection,
|
||||
get as getCachedProjection,
|
||||
toUserCoordinate,
|
||||
toUserExtent,
|
||||
} from '../proj.js';
|
||||
import {clamp} from '../math.js';
|
||||
import {create as createDecoderWorker} from '../worker/geotiff-decoder.js';
|
||||
import {getIntersection} from '../extent.js';
|
||||
import {getCenter, getIntersection} from '../extent.js';
|
||||
import {toSize} from '../size.js';
|
||||
import {fromCode as unitsFromCode} from '../proj/Units.js';
|
||||
|
||||
@@ -181,15 +186,18 @@ function getImagesForSource(source) {
|
||||
* @param {number|Array<number>|Array<Array<number>>} got Actual value.
|
||||
* @param {number} tolerance Accepted tolerance in fraction of expected between expected and got.
|
||||
* @param {string} message The error message.
|
||||
* @param {function(Error):void} rejector A function to be called with any error.
|
||||
*/
|
||||
function assertEqual(expected, got, tolerance, message) {
|
||||
function assertEqual(expected, got, tolerance, message, rejector) {
|
||||
if (Array.isArray(expected)) {
|
||||
const length = expected.length;
|
||||
if (!Array.isArray(got) || length != got.length) {
|
||||
throw new Error(message);
|
||||
const error = new Error(message);
|
||||
rejector(error);
|
||||
throw error;
|
||||
}
|
||||
for (let i = 0; i < length; ++i) {
|
||||
assertEqual(expected[i], got[i], tolerance, message);
|
||||
assertEqual(expected[i], got[i], tolerance, message, rejector);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -433,7 +441,7 @@ class GeoTIFFSource extends DataTile {
|
||||
origin = sourceOrigin;
|
||||
} else {
|
||||
const message = `Origin mismatch for source ${sourceIndex}, got [${sourceOrigin}] but expected [${origin}]`;
|
||||
assertEqual(origin, sourceOrigin, 0, message);
|
||||
assertEqual(origin, sourceOrigin, 0, message, this.viewRejector);
|
||||
}
|
||||
|
||||
if (!resolutions) {
|
||||
@@ -455,7 +463,8 @@ class GeoTIFFSource extends DataTile {
|
||||
resolutions.slice(minZoom, resolutions.length),
|
||||
scaledSourceResolutions,
|
||||
0.005,
|
||||
message
|
||||
message,
|
||||
this.viewRejector
|
||||
);
|
||||
}
|
||||
|
||||
@@ -466,7 +475,8 @@ class GeoTIFFSource extends DataTile {
|
||||
tileSizes.slice(minZoom, tileSizes.length),
|
||||
sourceTileSizes,
|
||||
0,
|
||||
`Tile size mismatch for source ${sourceIndex}`
|
||||
`Tile size mismatch for source ${sourceIndex}`,
|
||||
this.viewRejector
|
||||
);
|
||||
}
|
||||
|
||||
@@ -545,6 +555,13 @@ class GeoTIFFSource extends DataTile {
|
||||
|
||||
this.setLoader(this.loadTile_.bind(this));
|
||||
this.setState(State.READY);
|
||||
this.viewResolver({
|
||||
projection: this.projection,
|
||||
resolutions: resolutions,
|
||||
center: toUserCoordinate(getCenter(extent), this.projection),
|
||||
extent: toUserExtent(extent, this.projection),
|
||||
zoom: 0,
|
||||
});
|
||||
}
|
||||
|
||||
loadTile_(z, x, y) {
|
||||
@@ -650,4 +667,27 @@ class GeoTIFFSource extends DataTile {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a promise for view properties based on the source. Use the result of this function
|
||||
* as the `view` option in a map constructor.
|
||||
*
|
||||
* const source = new GeoTIFF(options);
|
||||
*
|
||||
* const map = new Map({
|
||||
* target: 'map',
|
||||
* layers: [
|
||||
* new TileLayer({
|
||||
* source: source,
|
||||
* }),
|
||||
* ],
|
||||
* view: source.getView(),
|
||||
* });
|
||||
*
|
||||
* @function
|
||||
* @return {Promise<import("../View.js").ViewOptions>} A promise for view-related properties.
|
||||
* @api
|
||||
*
|
||||
*/
|
||||
GeoTIFFSource.prototype.getView;
|
||||
|
||||
export default GeoTIFFSource;
|
||||
|
||||
@@ -90,6 +90,28 @@ class Source extends BaseObject {
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.wrapX_ = options.wrapX !== undefined ? options.wrapX : false;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {function(import("../View.js").ViewOptions):void}
|
||||
*/
|
||||
this.viewResolver = null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {function(Error):void}
|
||||
*/
|
||||
this.viewRejector = null;
|
||||
|
||||
const self = this;
|
||||
/**
|
||||
* @private
|
||||
* @type {Promise<import("../View.js").ViewOptions>}
|
||||
*/
|
||||
this.viewPromise_ = new Promise(function (resolve, reject) {
|
||||
self.viewResolver = resolve;
|
||||
self.viewRejector = reject;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,6 +148,13 @@ class Source extends BaseObject {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Promise<import("../View.js").ViewOptions>} A promise for view-related properties.
|
||||
*/
|
||||
getView() {
|
||||
return this.viewPromise_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the state of the source, see {@link module:ol/source/State~State} for possible states.
|
||||
* @return {import("./State.js").default} State.
|
||||
|
||||
Reference in New Issue
Block a user