ol-cesium
Version:
OpenLayers Cesium integration library
243 lines (207 loc) • 6.72 kB
JavaScript
/**
* @module olcs.core.OLImageryProvider
*/
import {get as getProjection} from 'ol/proj.js';
import olcsUtil from '../util.js';
class OLImageryProvider /* should not extend Cesium.ImageryProvider */ {
/**
* Special class derived from Cesium.ImageryProvider
* that is connected to the given ol.source.TileImage.
* @param {!ol.Map} olMap
* @param {!ol.source.TileImage} source
* @param {ol.proj.Projection=} opt_fallbackProj Projection to assume if the
* projection of the source is not defined.
* @constructor
* @extends {Cesium.ImageryProvider}
*/
constructor(olMap, source, opt_fallbackProj) {
// Do not extend or call super constructor from
// Cesium.ImageryProvider since this particular function is a
// 'non instanciable interface' which throws on instanciation.
/**
* @type {!ol.source.TileImage}
* @private
*/
this.source_ = source;
/**
* @type {?ol.proj.Projection}
* @private
*/
this.projection_ = null;
/**
* @type {?ol.proj.Projection}
* @private
*/
this.fallbackProj_ = opt_fallbackProj || null;
/**
* @type {boolean}
* @private
*/
this.ready_ = false;
/**
* @type {?Cesium.TilingScheme}
* @private
*/
this.tilingScheme_ = null;
/**
* @type {?Cesium.Rectangle}
* @private
*/
this.rectangle_ = null;
/**
* @type {!ol.Map}
* @private
*/
this.map_ = olMap;
const proxy = this.source_.get('olcs.proxy');
if (proxy) {
if (typeof proxy === 'function') {
this.proxy_ = {
'getURL': proxy
};
} else if (typeof proxy === 'string') {
this.proxy_ = new Cesium.DefaultProxy(proxy);
}
}
this.errorEvent_ = new Cesium.Event();
this.emptyCanvas_ = document.createElement('canvas');
this.emptyCanvas_.width = 1;
this.emptyCanvas_.height = 1;
this.source_.on('change', (e) => {
this.handleSourceChanged_();
});
this.handleSourceChanged_();
}
/**
* Checks if the underlying source is ready and cached required data.
* @private
*/
handleSourceChanged_(frameState) {
if (!this.ready_ && this.source_.getState() == 'ready') {
this.projection_ = olcsUtil.getSourceProjection(this.source_) || this.fallbackProj_;
if (this.projection_ == getProjection('EPSG:4326')) {
this.tilingScheme_ = new Cesium.GeographicTilingScheme();
} else if (this.projection_ == getProjection('EPSG:3857')) {
this.tilingScheme_ = new Cesium.WebMercatorTilingScheme();
} else {
return;
}
this.rectangle_ = this.tilingScheme_.rectangle;
this.ready_ = true;
}
}
/**
* Generates the proper attributions for a given position and zoom
* level.
* @export
* @override
*/
getTileCredits(x, y, level) {
const extent = this.map_.getView().calculateExtent(this.map_.getSize());
const center = this.map_.getView().getCenter();
const zoom = this.tilingScheme_ instanceof Cesium.GeographicTilingScheme ? level + 1 : level;
const frameState = {
viewState: {zoom, center},
extent,
};
const attributionsFunction = this.source_.getAttributions();
if (!attributionsFunction) {
return [];
}
let attributions = attributionsFunction(frameState);
if (!Array.isArray(attributions)) {
attributions = [attributions];
}
return attributions.map(html => new Cesium.Credit(html, true));
}
/**
* @export
* @override
*/
requestImage(x, y, level) {
const tileUrlFunction = this.source_.getTileUrlFunction();
if (tileUrlFunction && this.projection_) {
// Perform mapping of Cesium tile coordinates to OpenLayers tile coordinates:
// 1) Cesium zoom level 0 is OpenLayers zoom level 1 for EPSG:4326
const z_ = this.tilingScheme_ instanceof Cesium.GeographicTilingScheme ? level + 1 : level;
// 2) OpenLayers tile coordinates increase from bottom to top
const y_ = -y - 1;
let url = tileUrlFunction.call(this.source_,
[z_, x, y_], 1, this.projection_);
if (this.proxy_) {
url = this.proxy_.getURL(url);
}
return url ? Cesium.ImageryProvider.loadImage(this, url) : this.emptyCanvas_;
} else {
// return empty canvas to stop Cesium from retrying later
return this.emptyCanvas_;
}
}
}
// definitions of getters that are required to be present
// in the Cesium.ImageryProvider instance:
Object.defineProperties(OLImageryProvider.prototype, {
'ready': {
'get': /** @this {olcs.core.OLImageryProvider} */
function() {return this.ready_;}
},
'rectangle': {
'get': /** @this {olcs.core.OLImageryProvider} */
function() {return this.rectangle_;}
},
'tileWidth': {
'get': /** @this {olcs.core.OLImageryProvider} */
function() {
const tg = this.source_.getTileGrid();
return tg ? (Array.isArray(tg.getTileSize(0)) ? tg.getTileSize(0)[0] : tg.getTileSize(0)) : 256;
}
},
'tileHeight': {
'get': /** @this {olcs.core.OLImageryProvider} */
function() {
const tg = this.source_.getTileGrid();
return tg ? (Array.isArray(tg.getTileSize(0)) ? tg.getTileSize(0)[1] : tg.getTileSize(0)) : 256;
}
},
'maximumLevel': {
'get': /** @this {olcs.core.OLImageryProvider} */
function() {
const tg = this.source_.getTileGrid();
return tg ? tg.getMaxZoom() : 18;
}
},
'minimumLevel': {
'get': /** @this {olcs.core.OLImageryProvider} */
function() {
// WARNING: Do not use the minimum level (at least until the extent is
// properly set). Cesium assumes the minimumLevel to contain only
// a few tiles and tries to load them all at once -- this can
// freeze and/or crash the browser !
return 0;
//var tg = this.source_.getTileGrid();
//return tg ? tg.getMinZoom() : 0;
}
},
'tilingScheme': {
'get': /** @this {olcs.core.OLImageryProvider} */
function() {return this.tilingScheme_;}
},
'tileDiscardPolicy': {
'get': function() {return undefined;}
},
'errorEvent': {
'get': /** @this {olcs.core.OLImageryProvider} */
function() {return this.errorEvent_;}
},
'proxy': {
'get': /** @this {olcs.core.OLImageryProvider} */
function() {return this.proxy_;}
},
'hasAlphaChannel': {
'get': function() {return true;}
},
'pickFeatures': {
'get': function() {return undefined;}
}
});
export default OLImageryProvider;