Automated class transform

npx lebab --replace src --transform class
This commit is contained in:
Tim Schaub
2018-07-16 16:18:16 -06:00
parent 60e85e7d89
commit 7b4a73f3b9
145 changed files with 32887 additions and 33714 deletions

View File

@@ -41,60 +41,175 @@ import {createXYZ, extentFromProjection} from '../tilegrid.js';
* @param {module:ol/source/BingMaps~Options=} options Bing Maps options.
* @api
*/
const BingMaps = function(options) {
class BingMaps {
constructor(options) {
/**
* @private
* @type {boolean}
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : false;
TileImage.call(this, {
cacheSize: options.cacheSize,
crossOrigin: 'anonymous',
opaque: true,
projection: getProjection('EPSG:3857'),
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
state: SourceState.LOADING,
tileLoadFunction: options.tileLoadFunction,
tilePixelRatio: this.hidpi_ ? 2 : 1,
wrapX: options.wrapX !== undefined ? options.wrapX : true,
transition: options.transition
});
/**
* @private
* @type {string}
*/
this.culture_ = options.culture !== undefined ? options.culture : 'en-us';
/**
* @private
* @type {number}
*/
this.maxZoom_ = options.maxZoom !== undefined ? options.maxZoom : -1;
/**
* @private
* @type {string}
*/
this.apiKey_ = options.key;
/**
* @private
* @type {string}
*/
this.imagerySet_ = options.imagerySet;
const url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/' +
this.imagerySet_ +
'?uriScheme=https&include=ImageryProviders&key=' + this.apiKey_ +
'&c=' + this.culture_;
requestJSONP(url, this.handleImageryMetadataResponse.bind(this), undefined,
'jsonp');
}
/**
* @private
* @type {boolean}
* Get the api key used for this source.
*
* @return {string} The api key.
* @api
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : false;
TileImage.call(this, {
cacheSize: options.cacheSize,
crossOrigin: 'anonymous',
opaque: true,
projection: getProjection('EPSG:3857'),
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
state: SourceState.LOADING,
tileLoadFunction: options.tileLoadFunction,
tilePixelRatio: this.hidpi_ ? 2 : 1,
wrapX: options.wrapX !== undefined ? options.wrapX : true,
transition: options.transition
});
getApiKey() {
return this.apiKey_;
}
/**
* @private
* @type {string}
* Get the imagery set associated with this source.
*
* @return {string} The imagery set.
* @api
*/
this.culture_ = options.culture !== undefined ? options.culture : 'en-us';
getImagerySet() {
return this.imagerySet_;
}
/**
* @private
* @type {number}
* @param {BingMapsImageryMetadataResponse} response Response.
*/
this.maxZoom_ = options.maxZoom !== undefined ? options.maxZoom : -1;
handleImageryMetadataResponse(response) {
if (response.statusCode != 200 ||
response.statusDescription != 'OK' ||
response.authenticationResultCode != 'ValidCredentials' ||
response.resourceSets.length != 1 ||
response.resourceSets[0].resources.length != 1) {
this.setState(SourceState.ERROR);
return;
}
/**
* @private
* @type {string}
*/
this.apiKey_ = options.key;
const resource = response.resourceSets[0].resources[0];
const maxZoom = this.maxZoom_ == -1 ? resource.zoomMax : this.maxZoom_;
/**
* @private
* @type {string}
*/
this.imagerySet_ = options.imagerySet;
const sourceProjection = this.getProjection();
const extent = extentFromProjection(sourceProjection);
const tileSize = resource.imageWidth == resource.imageHeight ?
resource.imageWidth : [resource.imageWidth, resource.imageHeight];
const tileGrid = createXYZ({
extent: extent,
minZoom: resource.zoomMin,
maxZoom: maxZoom,
tileSize: tileSize / (this.hidpi_ ? 2 : 1)
});
this.tileGrid = tileGrid;
const url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/' +
this.imagerySet_ +
'?uriScheme=https&include=ImageryProviders&key=' + this.apiKey_ +
'&c=' + this.culture_;
const culture = this.culture_;
const hidpi = this.hidpi_;
this.tileUrlFunction = createFromTileUrlFunctions(
resource.imageUrlSubdomains.map(function(subdomain) {
const quadKeyTileCoord = [0, 0, 0];
const imageUrl = resource.imageUrl
.replace('{subdomain}', subdomain)
.replace('{culture}', culture);
return (
/**
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
function(tileCoord, pixelRatio, projection) {
if (!tileCoord) {
return undefined;
} else {
createOrUpdate(tileCoord[0], tileCoord[1], -tileCoord[2] - 1, quadKeyTileCoord);
let url = imageUrl;
if (hidpi) {
url += '&dpi=d1&device=mobile';
}
return url.replace('{quadkey}', quadKey(quadKeyTileCoord));
}
}
);
}));
requestJSONP(url, this.handleImageryMetadataResponse.bind(this), undefined,
'jsonp');
if (resource.imageryProviders) {
const transform = getTransformFromProjections(
getProjection('EPSG:4326'), this.getProjection());
};
this.setAttributions(function(frameState) {
const attributions = [];
const zoom = frameState.viewState.zoom;
resource.imageryProviders.map(function(imageryProvider) {
let intersecting = false;
const coverageAreas = imageryProvider.coverageAreas;
for (let i = 0, ii = coverageAreas.length; i < ii; ++i) {
const coverageArea = coverageAreas[i];
if (zoom >= coverageArea.zoomMin && zoom <= coverageArea.zoomMax) {
const bbox = coverageArea.bbox;
const epsg4326Extent = [bbox[1], bbox[0], bbox[3], bbox[2]];
const extent = applyTransform(epsg4326Extent, transform);
if (intersects(extent, frameState.extent)) {
intersecting = true;
break;
}
}
}
if (intersecting) {
attributions.push(imageryProvider.attribution);
}
});
attributions.push(TOS_ATTRIBUTION);
return attributions;
});
}
this.setState(SourceState.READY);
}
}
inherits(BingMaps, TileImage);
@@ -110,118 +225,4 @@ const TOS_ATTRIBUTION = '<a class="ol-attribution-bing-tos" ' +
'Terms of Use</a>';
/**
* Get the api key used for this source.
*
* @return {string} The api key.
* @api
*/
BingMaps.prototype.getApiKey = function() {
return this.apiKey_;
};
/**
* Get the imagery set associated with this source.
*
* @return {string} The imagery set.
* @api
*/
BingMaps.prototype.getImagerySet = function() {
return this.imagerySet_;
};
/**
* @param {BingMapsImageryMetadataResponse} response Response.
*/
BingMaps.prototype.handleImageryMetadataResponse = function(response) {
if (response.statusCode != 200 ||
response.statusDescription != 'OK' ||
response.authenticationResultCode != 'ValidCredentials' ||
response.resourceSets.length != 1 ||
response.resourceSets[0].resources.length != 1) {
this.setState(SourceState.ERROR);
return;
}
const resource = response.resourceSets[0].resources[0];
const maxZoom = this.maxZoom_ == -1 ? resource.zoomMax : this.maxZoom_;
const sourceProjection = this.getProjection();
const extent = extentFromProjection(sourceProjection);
const tileSize = resource.imageWidth == resource.imageHeight ?
resource.imageWidth : [resource.imageWidth, resource.imageHeight];
const tileGrid = createXYZ({
extent: extent,
minZoom: resource.zoomMin,
maxZoom: maxZoom,
tileSize: tileSize / (this.hidpi_ ? 2 : 1)
});
this.tileGrid = tileGrid;
const culture = this.culture_;
const hidpi = this.hidpi_;
this.tileUrlFunction = createFromTileUrlFunctions(
resource.imageUrlSubdomains.map(function(subdomain) {
const quadKeyTileCoord = [0, 0, 0];
const imageUrl = resource.imageUrl
.replace('{subdomain}', subdomain)
.replace('{culture}', culture);
return (
/**
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
function(tileCoord, pixelRatio, projection) {
if (!tileCoord) {
return undefined;
} else {
createOrUpdate(tileCoord[0], tileCoord[1], -tileCoord[2] - 1, quadKeyTileCoord);
let url = imageUrl;
if (hidpi) {
url += '&dpi=d1&device=mobile';
}
return url.replace('{quadkey}', quadKey(quadKeyTileCoord));
}
}
);
}));
if (resource.imageryProviders) {
const transform = getTransformFromProjections(
getProjection('EPSG:4326'), this.getProjection());
this.setAttributions(function(frameState) {
const attributions = [];
const zoom = frameState.viewState.zoom;
resource.imageryProviders.map(function(imageryProvider) {
let intersecting = false;
const coverageAreas = imageryProvider.coverageAreas;
for (let i = 0, ii = coverageAreas.length; i < ii; ++i) {
const coverageArea = coverageAreas[i];
if (zoom >= coverageArea.zoomMin && zoom <= coverageArea.zoomMax) {
const bbox = coverageArea.bbox;
const epsg4326Extent = [bbox[1], bbox[0], bbox[3], bbox[2]];
const extent = applyTransform(epsg4326Extent, transform);
if (intersects(extent, frameState.extent)) {
intersecting = true;
break;
}
}
}
if (intersecting) {
attributions.push(imageryProvider.attribution);
}
});
attributions.push(TOS_ATTRIBUTION);
return attributions;
});
}
this.setState(SourceState.READY);
};
export default BingMaps;

View File

@@ -40,152 +40,149 @@ import XYZ from '../source/XYZ.js';
* @param {module:ol/source/CartoDB~Options=} options CartoDB options.
* @api
*/
const CartoDB = function(options) {
class CartoDB {
constructor(options) {
/**
* @type {string}
* @private
*/
this.account_ = options.account;
/**
* @type {string}
* @private
*/
this.mapId_ = options.map || '';
/**
* @type {!Object}
* @private
*/
this.config_ = options.config || {};
/**
* @type {!Object.<string, CartoDBLayerInfo>}
* @private
*/
this.templateCache_ = {};
XYZ.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
maxZoom: options.maxZoom !== undefined ? options.maxZoom : 18,
minZoom: options.minZoom,
projection: options.projection,
state: SourceState.LOADING,
wrapX: options.wrapX
});
this.initializeMap_();
}
/**
* @type {string}
* @private
* Returns the current config.
* @return {!Object} The current configuration.
* @api
*/
this.account_ = options.account;
getConfig() {
return this.config_;
}
/**
* @type {string}
* @private
* Updates the carto db config.
* @param {Object} config a key-value lookup. Values will replace current values
* in the config.
* @api
*/
this.mapId_ = options.map || '';
updateConfig(config) {
assign(this.config_, config);
this.initializeMap_();
}
/**
* @type {!Object}
* @private
* Sets the CartoDB config
* @param {Object} config In the case of anonymous maps, a CartoDB configuration
* object.
* If using named maps, a key-value lookup with the template parameters.
* @api
*/
this.config_ = options.config || {};
setConfig(config) {
this.config_ = config || {};
this.initializeMap_();
}
/**
* @type {!Object.<string, CartoDBLayerInfo>}
* Issue a request to initialize the CartoDB map.
* @private
*/
this.templateCache_ = {};
initializeMap_() {
const paramHash = JSON.stringify(this.config_);
if (this.templateCache_[paramHash]) {
this.applyTemplate_(this.templateCache_[paramHash]);
return;
}
let mapUrl = 'https://' + this.account_ + '.carto.com/api/v1/map';
XYZ.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
maxZoom: options.maxZoom !== undefined ? options.maxZoom : 18,
minZoom: options.minZoom,
projection: options.projection,
state: SourceState.LOADING,
wrapX: options.wrapX
});
this.initializeMap_();
};
if (this.mapId_) {
mapUrl += '/named/' + this.mapId_;
}
const client = new XMLHttpRequest();
client.addEventListener('load', this.handleInitResponse_.bind(this, paramHash));
client.addEventListener('error', this.handleInitError_.bind(this));
client.open('POST', mapUrl);
client.setRequestHeader('Content-type', 'application/json');
client.send(JSON.stringify(this.config_));
}
/**
* Handle map initialization response.
* @param {string} paramHash a hash representing the parameter set that was used
* for the request
* @param {Event} event Event.
* @private
*/
handleInitResponse_(paramHash, event) {
const client = /** @type {XMLHttpRequest} */ (event.target);
// status will be 0 for file:// urls
if (!client.status || client.status >= 200 && client.status < 300) {
let response;
try {
response = /** @type {CartoDBLayerInfo} */(JSON.parse(client.responseText));
} catch (err) {
this.setState(SourceState.ERROR);
return;
}
this.applyTemplate_(response);
this.templateCache_[paramHash] = response;
this.setState(SourceState.READY);
} else {
this.setState(SourceState.ERROR);
}
}
/**
* @private
* @param {Event} event Event.
*/
handleInitError_(event) {
this.setState(SourceState.ERROR);
}
/**
* Apply the new tile urls returned by carto db
* @param {CartoDBLayerInfo} data Result of carto db call.
* @private
*/
applyTemplate_(data) {
const tilesUrl = 'https://' + data.cdn_url.https + '/' + this.account_ +
'/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png';
this.setUrl(tilesUrl);
}
}
inherits(CartoDB, XYZ);
/**
* Returns the current config.
* @return {!Object} The current configuration.
* @api
*/
CartoDB.prototype.getConfig = function() {
return this.config_;
};
/**
* Updates the carto db config.
* @param {Object} config a key-value lookup. Values will replace current values
* in the config.
* @api
*/
CartoDB.prototype.updateConfig = function(config) {
assign(this.config_, config);
this.initializeMap_();
};
/**
* Sets the CartoDB config
* @param {Object} config In the case of anonymous maps, a CartoDB configuration
* object.
* If using named maps, a key-value lookup with the template parameters.
* @api
*/
CartoDB.prototype.setConfig = function(config) {
this.config_ = config || {};
this.initializeMap_();
};
/**
* Issue a request to initialize the CartoDB map.
* @private
*/
CartoDB.prototype.initializeMap_ = function() {
const paramHash = JSON.stringify(this.config_);
if (this.templateCache_[paramHash]) {
this.applyTemplate_(this.templateCache_[paramHash]);
return;
}
let mapUrl = 'https://' + this.account_ + '.carto.com/api/v1/map';
if (this.mapId_) {
mapUrl += '/named/' + this.mapId_;
}
const client = new XMLHttpRequest();
client.addEventListener('load', this.handleInitResponse_.bind(this, paramHash));
client.addEventListener('error', this.handleInitError_.bind(this));
client.open('POST', mapUrl);
client.setRequestHeader('Content-type', 'application/json');
client.send(JSON.stringify(this.config_));
};
/**
* Handle map initialization response.
* @param {string} paramHash a hash representing the parameter set that was used
* for the request
* @param {Event} event Event.
* @private
*/
CartoDB.prototype.handleInitResponse_ = function(paramHash, event) {
const client = /** @type {XMLHttpRequest} */ (event.target);
// status will be 0 for file:// urls
if (!client.status || client.status >= 200 && client.status < 300) {
let response;
try {
response = /** @type {CartoDBLayerInfo} */(JSON.parse(client.responseText));
} catch (err) {
this.setState(SourceState.ERROR);
return;
}
this.applyTemplate_(response);
this.templateCache_[paramHash] = response;
this.setState(SourceState.READY);
} else {
this.setState(SourceState.ERROR);
}
};
/**
* @private
* @param {Event} event Event.
*/
CartoDB.prototype.handleInitError_ = function(event) {
this.setState(SourceState.ERROR);
};
/**
* Apply the new tile urls returned by carto db
* @param {CartoDBLayerInfo} data Result of carto db call.
* @private
*/
CartoDB.prototype.applyTemplate_ = function(data) {
const tilesUrl = 'https://' + data.cdn_url.https + '/' + this.account_ +
'/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png';
this.setUrl(tilesUrl);
};
export default CartoDB;

View File

@@ -47,175 +47,172 @@ import VectorSource from '../source/Vector.js';
* @extends {module:ol/source/Vector}
* @api
*/
const Cluster = function(options) {
VectorSource.call(this, {
attributions: options.attributions,
extent: options.extent,
projection: options.projection,
wrapX: options.wrapX
});
class Cluster {
constructor(options) {
VectorSource.call(this, {
attributions: options.attributions,
extent: options.extent,
projection: options.projection,
wrapX: options.wrapX
});
/**
* @type {number|undefined}
* @protected
*/
this.resolution = undefined;
/**
* @type {number}
* @protected
*/
this.distance = options.distance !== undefined ? options.distance : 20;
/**
* @type {Array.<module:ol/Feature>}
* @protected
*/
this.features = [];
/**
* @param {module:ol/Feature} feature Feature.
* @return {module:ol/geom/Point} Cluster calculation point.
* @protected
*/
this.geometryFunction = options.geometryFunction || function(feature) {
const geometry = /** @type {module:ol/geom/Point} */ (feature.getGeometry());
assert(geometry instanceof Point,
10); // The default `geometryFunction` can only handle `module:ol/geom/Point~Point` geometries
return geometry;
};
/**
* @type {module:ol/source/Vector}
* @protected
*/
this.source = options.source;
listen(this.source, EventType.CHANGE, this.refresh, this);
}
/**
* @type {number|undefined}
* @protected
* Get the distance in pixels between clusters.
* @return {number} Distance.
* @api
*/
this.resolution = undefined;
getDistance() {
return this.distance;
}
/**
* @type {number}
* @protected
* Get a reference to the wrapped source.
* @return {module:ol/source/Vector} Source.
* @api
*/
this.distance = options.distance !== undefined ? options.distance : 20;
getSource() {
return this.source;
}
/**
* @type {Array.<module:ol/Feature>}
* @protected
* @inheritDoc
*/
this.features = [];
loadFeatures(extent, resolution, projection) {
this.source.loadFeatures(extent, resolution, projection);
if (resolution !== this.resolution) {
this.clear();
this.resolution = resolution;
this.cluster();
this.addFeatures(this.features);
}
}
/**
* @param {module:ol/Feature} feature Feature.
* @return {module:ol/geom/Point} Cluster calculation point.
* @protected
* Set the distance in pixels between clusters.
* @param {number} distance The distance in pixels.
* @api
*/
this.geometryFunction = options.geometryFunction || function(feature) {
const geometry = /** @type {module:ol/geom/Point} */ (feature.getGeometry());
assert(geometry instanceof Point,
10); // The default `geometryFunction` can only handle `module:ol/geom/Point~Point` geometries
return geometry;
};
setDistance(distance) {
this.distance = distance;
this.refresh();
}
/**
* handle the source changing
* @override
*/
refresh() {
this.clear();
this.cluster();
this.addFeatures(this.features);
VectorSource.prototype.refresh.call(this);
}
/**
* @type {module:ol/source/Vector}
* @protected
*/
this.source = options.source;
cluster() {
if (this.resolution === undefined) {
return;
}
this.features.length = 0;
const extent = createEmpty();
const mapDistance = this.distance * this.resolution;
const features = this.source.getFeatures();
listen(this.source, EventType.CHANGE, this.refresh, this);
};
/**
* @type {!Object.<string, boolean>}
*/
const clustered = {};
for (let i = 0, ii = features.length; i < ii; i++) {
const feature = features[i];
if (!(getUid(feature).toString() in clustered)) {
const geometry = this.geometryFunction(feature);
if (geometry) {
const coordinates = geometry.getCoordinates();
createOrUpdateFromCoordinate(coordinates, extent);
buffer(extent, mapDistance, extent);
let neighbors = this.source.getFeaturesInExtent(extent);
neighbors = neighbors.filter(function(neighbor) {
const uid = getUid(neighbor).toString();
if (!(uid in clustered)) {
clustered[uid] = true;
return true;
} else {
return false;
}
});
this.features.push(this.createCluster(neighbors));
}
}
}
}
/**
* @param {Array.<module:ol/Feature>} features Features
* @return {module:ol/Feature} The cluster feature.
* @protected
*/
createCluster(features) {
const centroid = [0, 0];
for (let i = features.length - 1; i >= 0; --i) {
const geometry = this.geometryFunction(features[i]);
if (geometry) {
addCoordinate(centroid, geometry.getCoordinates());
} else {
features.splice(i, 1);
}
}
scaleCoordinate(centroid, 1 / features.length);
const cluster = new Feature(new Point(centroid));
cluster.set('features', features);
return cluster;
}
}
inherits(Cluster, VectorSource);
/**
* Get the distance in pixels between clusters.
* @return {number} Distance.
* @api
*/
Cluster.prototype.getDistance = function() {
return this.distance;
};
/**
* Get a reference to the wrapped source.
* @return {module:ol/source/Vector} Source.
* @api
*/
Cluster.prototype.getSource = function() {
return this.source;
};
/**
* @inheritDoc
*/
Cluster.prototype.loadFeatures = function(extent, resolution, projection) {
this.source.loadFeatures(extent, resolution, projection);
if (resolution !== this.resolution) {
this.clear();
this.resolution = resolution;
this.cluster();
this.addFeatures(this.features);
}
};
/**
* Set the distance in pixels between clusters.
* @param {number} distance The distance in pixels.
* @api
*/
Cluster.prototype.setDistance = function(distance) {
this.distance = distance;
this.refresh();
};
/**
* handle the source changing
* @override
*/
Cluster.prototype.refresh = function() {
this.clear();
this.cluster();
this.addFeatures(this.features);
VectorSource.prototype.refresh.call(this);
};
/**
* @protected
*/
Cluster.prototype.cluster = function() {
if (this.resolution === undefined) {
return;
}
this.features.length = 0;
const extent = createEmpty();
const mapDistance = this.distance * this.resolution;
const features = this.source.getFeatures();
/**
* @type {!Object.<string, boolean>}
*/
const clustered = {};
for (let i = 0, ii = features.length; i < ii; i++) {
const feature = features[i];
if (!(getUid(feature).toString() in clustered)) {
const geometry = this.geometryFunction(feature);
if (geometry) {
const coordinates = geometry.getCoordinates();
createOrUpdateFromCoordinate(coordinates, extent);
buffer(extent, mapDistance, extent);
let neighbors = this.source.getFeaturesInExtent(extent);
neighbors = neighbors.filter(function(neighbor) {
const uid = getUid(neighbor).toString();
if (!(uid in clustered)) {
clustered[uid] = true;
return true;
} else {
return false;
}
});
this.features.push(this.createCluster(neighbors));
}
}
}
};
/**
* @param {Array.<module:ol/Feature>} features Features
* @return {module:ol/Feature} The cluster feature.
* @protected
*/
Cluster.prototype.createCluster = function(features) {
const centroid = [0, 0];
for (let i = features.length - 1; i >= 0; --i) {
const geometry = this.geometryFunction(features[i]);
if (geometry) {
addCoordinate(centroid, geometry.getCoordinates());
} else {
features.splice(i, 1);
}
}
scaleCoordinate(centroid, 1 / features.length);
const cluster = new Feature(new Point(centroid));
cluster.set('features', features);
return cluster;
};
export default Cluster;

View File

@@ -88,146 +88,143 @@ inherits(ImageSourceEvent, Event);
* @param {module:ol/source/Image~Options} options Single image source options.
* @api
*/
const ImageSource = function(options) {
Source.call(this, {
attributions: options.attributions,
extent: options.extent,
projection: options.projection,
state: options.state
});
class ImageSource {
constructor(options) {
Source.call(this, {
attributions: options.attributions,
extent: options.extent,
projection: options.projection,
state: options.state
});
/**
* @private
* @type {Array.<number>}
*/
this.resolutions_ = options.resolutions !== undefined ?
options.resolutions : null;
/**
* @private
* @type {module:ol/reproj/Image}
*/
this.reprojectedImage_ = null;
/**
* @private
* @type {number}
*/
this.reprojectedRevision_ = 0;
}
/**
* @private
* @type {Array.<number>}
* @return {Array.<number>} Resolutions.
* @override
*/
this.resolutions_ = options.resolutions !== undefined ?
options.resolutions : null;
getResolutions() {
return this.resolutions_;
}
/**
* @private
* @type {module:ol/reproj/Image}
* @protected
* @param {number} resolution Resolution.
* @return {number} Resolution.
*/
this.reprojectedImage_ = null;
findNearestResolution(resolution) {
if (this.resolutions_) {
const idx = linearFindNearest(this.resolutions_, resolution, 0);
resolution = this.resolutions_[idx];
}
return resolution;
}
/**
* @private
* @type {number}
* @param {module:ol/extent~Extent} extent Extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @return {module:ol/ImageBase} Single image.
*/
this.reprojectedRevision_ = 0;
};
getImage(extent, resolution, pixelRatio, projection) {
const sourceProjection = this.getProjection();
if (!ENABLE_RASTER_REPROJECTION ||
!sourceProjection ||
!projection ||
equivalent(sourceProjection, projection)) {
if (sourceProjection) {
projection = sourceProjection;
}
return this.getImageInternal(extent, resolution, pixelRatio, projection);
} else {
if (this.reprojectedImage_) {
if (this.reprojectedRevision_ == this.getRevision() &&
equivalent(
this.reprojectedImage_.getProjection(), projection) &&
this.reprojectedImage_.getResolution() == resolution &&
equals(this.reprojectedImage_.getExtent(), extent)) {
return this.reprojectedImage_;
}
this.reprojectedImage_.dispose();
this.reprojectedImage_ = null;
}
this.reprojectedImage_ = new ReprojImage(
sourceProjection, projection, extent, resolution, pixelRatio,
function(extent, resolution, pixelRatio) {
return this.getImageInternal(extent, resolution,
pixelRatio, sourceProjection);
}.bind(this));
this.reprojectedRevision_ = this.getRevision();
return this.reprojectedImage_;
}
}
/**
* @abstract
* @param {module:ol/extent~Extent} extent Extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @return {module:ol/ImageBase} Single image.
* @protected
*/
getImageInternal(extent, resolution, pixelRatio, projection) {}
/**
* Handle image change events.
* @param {module:ol/events/Event} event Event.
* @protected
*/
handleImageChange(event) {
const image = /** @type {module:ol/Image} */ (event.target);
switch (image.getState()) {
case ImageState.LOADING:
this.dispatchEvent(
new ImageSourceEvent(ImageSourceEventType.IMAGELOADSTART,
image));
break;
case ImageState.LOADED:
this.dispatchEvent(
new ImageSourceEvent(ImageSourceEventType.IMAGELOADEND,
image));
break;
case ImageState.ERROR:
this.dispatchEvent(
new ImageSourceEvent(ImageSourceEventType.IMAGELOADERROR,
image));
break;
default:
// pass
}
}
}
inherits(ImageSource, Source);
/**
* @return {Array.<number>} Resolutions.
* @override
*/
ImageSource.prototype.getResolutions = function() {
return this.resolutions_;
};
/**
* @protected
* @param {number} resolution Resolution.
* @return {number} Resolution.
*/
ImageSource.prototype.findNearestResolution = function(resolution) {
if (this.resolutions_) {
const idx = linearFindNearest(this.resolutions_, resolution, 0);
resolution = this.resolutions_[idx];
}
return resolution;
};
/**
* @param {module:ol/extent~Extent} extent Extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @return {module:ol/ImageBase} Single image.
*/
ImageSource.prototype.getImage = function(extent, resolution, pixelRatio, projection) {
const sourceProjection = this.getProjection();
if (!ENABLE_RASTER_REPROJECTION ||
!sourceProjection ||
!projection ||
equivalent(sourceProjection, projection)) {
if (sourceProjection) {
projection = sourceProjection;
}
return this.getImageInternal(extent, resolution, pixelRatio, projection);
} else {
if (this.reprojectedImage_) {
if (this.reprojectedRevision_ == this.getRevision() &&
equivalent(
this.reprojectedImage_.getProjection(), projection) &&
this.reprojectedImage_.getResolution() == resolution &&
equals(this.reprojectedImage_.getExtent(), extent)) {
return this.reprojectedImage_;
}
this.reprojectedImage_.dispose();
this.reprojectedImage_ = null;
}
this.reprojectedImage_ = new ReprojImage(
sourceProjection, projection, extent, resolution, pixelRatio,
function(extent, resolution, pixelRatio) {
return this.getImageInternal(extent, resolution,
pixelRatio, sourceProjection);
}.bind(this));
this.reprojectedRevision_ = this.getRevision();
return this.reprojectedImage_;
}
};
/**
* @abstract
* @param {module:ol/extent~Extent} extent Extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @return {module:ol/ImageBase} Single image.
* @protected
*/
ImageSource.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {};
/**
* Handle image change events.
* @param {module:ol/events/Event} event Event.
* @protected
*/
ImageSource.prototype.handleImageChange = function(event) {
const image = /** @type {module:ol/Image} */ (event.target);
switch (image.getState()) {
case ImageState.LOADING:
this.dispatchEvent(
new ImageSourceEvent(ImageSourceEventType.IMAGELOADSTART,
image));
break;
case ImageState.LOADED:
this.dispatchEvent(
new ImageSourceEvent(ImageSourceEventType.IMAGELOADEND,
image));
break;
case ImageState.ERROR:
this.dispatchEvent(
new ImageSourceEvent(ImageSourceEventType.IMAGELOADERROR,
image));
break;
default:
// pass
}
};
/**
* Default image load function for image sources that use module:ol/Image~Image image
* instances.

View File

@@ -54,246 +54,242 @@ import {appendParams} from '../uri.js';
* @param {module:ol/source/ImageArcGISRest~Options=} opt_options Image ArcGIS Rest Options.
* @api
*/
const ImageArcGISRest = function(opt_options) {
class ImageArcGISRest {
constructor(opt_options) {
const options = opt_options || {};
const options = opt_options || {};
ImageSource.call(this, {
attributions: options.attributions,
projection: options.projection,
resolutions: options.resolutions
});
ImageSource.call(this, {
attributions: options.attributions,
projection: options.projection,
resolutions: options.resolutions
});
/**
* @private
* @type {?string}
*/
this.crossOrigin_ =
options.crossOrigin !== undefined ? options.crossOrigin : null;
/**
* @private
* @type {boolean}
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
/**
* @private
* @type {string|undefined}
*/
this.url_ = options.url;
/**
* @private
* @type {module:ol/Image~LoadFunction}
*/
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
options.imageLoadFunction : defaultImageLoadFunction;
/**
* @private
* @type {!Object}
*/
this.params_ = options.params || {};
/**
* @private
* @type {module:ol/Image}
*/
this.image_ = null;
/**
* @private
* @type {module:ol/size~Size}
*/
this.imageSize_ = [0, 0];
/**
* @private
* @type {number}
*/
this.renderedRevision_ = 0;
/**
* @private
* @type {number}
*/
this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
}
/**
* @private
* @type {?string}
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
this.crossOrigin_ =
options.crossOrigin !== undefined ? options.crossOrigin : null;
getParams() {
return this.params_;
}
/**
* @private
* @type {boolean}
* @inheritDoc
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
getImageInternal(extent, resolution, pixelRatio, projection) {
if (this.url_ === undefined) {
return null;
}
resolution = this.findNearestResolution(resolution);
pixelRatio = this.hidpi_ ? pixelRatio : 1;
const image = this.image_;
if (image &&
this.renderedRevision_ == this.getRevision() &&
image.getResolution() == resolution &&
image.getPixelRatio() == pixelRatio &&
containsExtent(image.getExtent(), extent)) {
return image;
}
const params = {
'F': 'image',
'FORMAT': 'PNG32',
'TRANSPARENT': true
};
assign(params, this.params_);
extent = extent.slice();
const centerX = (extent[0] + extent[2]) / 2;
const centerY = (extent[1] + extent[3]) / 2;
if (this.ratio_ != 1) {
const halfWidth = this.ratio_ * getWidth(extent) / 2;
const halfHeight = this.ratio_ * getHeight(extent) / 2;
extent[0] = centerX - halfWidth;
extent[1] = centerY - halfHeight;
extent[2] = centerX + halfWidth;
extent[3] = centerY + halfHeight;
}
const imageResolution = resolution / pixelRatio;
// Compute an integer width and height.
const width = Math.ceil(getWidth(extent) / imageResolution);
const height = Math.ceil(getHeight(extent) / imageResolution);
// Modify the extent to match the integer width and height.
extent[0] = centerX - imageResolution * width / 2;
extent[2] = centerX + imageResolution * width / 2;
extent[1] = centerY - imageResolution * height / 2;
extent[3] = centerY + imageResolution * height / 2;
this.imageSize_[0] = width;
this.imageSize_[1] = height;
const url = this.getRequestUrl_(extent, this.imageSize_, pixelRatio,
projection, params);
this.image_ = new ImageWrapper(extent, resolution, pixelRatio,
url, this.crossOrigin_, this.imageLoadFunction_);
this.renderedRevision_ = this.getRevision();
listen(this.image_, EventType.CHANGE,
this.handleImageChange, this);
return this.image_;
}
/**
* @private
* @type {string|undefined}
* Return the image load function of the source.
* @return {module:ol/Image~LoadFunction} The image load function.
* @api
*/
this.url_ = options.url;
getImageLoadFunction() {
return this.imageLoadFunction_;
}
/**
* @param {module:ol/extent~Extent} extent Extent.
* @param {module:ol/size~Size} size Size.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @param {Object} params Params.
* @return {string} Request URL.
* @private
* @type {module:ol/Image~LoadFunction}
*/
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
options.imageLoadFunction : defaultImageLoadFunction;
getRequestUrl_(extent, size, pixelRatio, projection, params) {
// ArcGIS Server only wants the numeric portion of the projection ID.
const srid = projection.getCode().split(':').pop();
params['SIZE'] = size[0] + ',' + size[1];
params['BBOX'] = extent.join(',');
params['BBOXSR'] = srid;
params['IMAGESR'] = srid;
params['DPI'] = Math.round(90 * pixelRatio);
const url = this.url_;
const modifiedUrl = url
.replace(/MapServer\/?$/, 'MapServer/export')
.replace(/ImageServer\/?$/, 'ImageServer/exportImage');
if (modifiedUrl == url) {
assert(false, 50); // `options.featureTypes` should be an Array
}
return appendParams(modifiedUrl, params);
}
/**
* @private
* @type {!Object}
* Return the URL used for this ArcGIS source.
* @return {string|undefined} URL.
* @api
*/
this.params_ = options.params || {};
getUrl() {
return this.url_;
}
/**
* @private
* @type {module:ol/Image}
* Set the image load function of the source.
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
* @api
*/
this.image_ = null;
setImageLoadFunction(imageLoadFunction) {
this.image_ = null;
this.imageLoadFunction_ = imageLoadFunction;
this.changed();
}
/**
* @private
* @type {module:ol/size~Size}
* Set the URL to use for requests.
* @param {string|undefined} url URL.
* @api
*/
this.imageSize_ = [0, 0];
setUrl(url) {
if (url != this.url_) {
this.url_ = url;
this.image_ = null;
this.changed();
}
}
/**
* @private
* @type {number}
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
this.renderedRevision_ = 0;
/**
* @private
* @type {number}
*/
this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
};
updateParams(params) {
assign(this.params_, params);
this.image_ = null;
this.changed();
}
}
inherits(ImageArcGISRest, ImageSource);
/**
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
ImageArcGISRest.prototype.getParams = function() {
return this.params_;
};
/**
* @inheritDoc
*/
ImageArcGISRest.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
if (this.url_ === undefined) {
return null;
}
resolution = this.findNearestResolution(resolution);
pixelRatio = this.hidpi_ ? pixelRatio : 1;
const image = this.image_;
if (image &&
this.renderedRevision_ == this.getRevision() &&
image.getResolution() == resolution &&
image.getPixelRatio() == pixelRatio &&
containsExtent(image.getExtent(), extent)) {
return image;
}
const params = {
'F': 'image',
'FORMAT': 'PNG32',
'TRANSPARENT': true
};
assign(params, this.params_);
extent = extent.slice();
const centerX = (extent[0] + extent[2]) / 2;
const centerY = (extent[1] + extent[3]) / 2;
if (this.ratio_ != 1) {
const halfWidth = this.ratio_ * getWidth(extent) / 2;
const halfHeight = this.ratio_ * getHeight(extent) / 2;
extent[0] = centerX - halfWidth;
extent[1] = centerY - halfHeight;
extent[2] = centerX + halfWidth;
extent[3] = centerY + halfHeight;
}
const imageResolution = resolution / pixelRatio;
// Compute an integer width and height.
const width = Math.ceil(getWidth(extent) / imageResolution);
const height = Math.ceil(getHeight(extent) / imageResolution);
// Modify the extent to match the integer width and height.
extent[0] = centerX - imageResolution * width / 2;
extent[2] = centerX + imageResolution * width / 2;
extent[1] = centerY - imageResolution * height / 2;
extent[3] = centerY + imageResolution * height / 2;
this.imageSize_[0] = width;
this.imageSize_[1] = height;
const url = this.getRequestUrl_(extent, this.imageSize_, pixelRatio,
projection, params);
this.image_ = new ImageWrapper(extent, resolution, pixelRatio,
url, this.crossOrigin_, this.imageLoadFunction_);
this.renderedRevision_ = this.getRevision();
listen(this.image_, EventType.CHANGE,
this.handleImageChange, this);
return this.image_;
};
/**
* Return the image load function of the source.
* @return {module:ol/Image~LoadFunction} The image load function.
* @api
*/
ImageArcGISRest.prototype.getImageLoadFunction = function() {
return this.imageLoadFunction_;
};
/**
* @param {module:ol/extent~Extent} extent Extent.
* @param {module:ol/size~Size} size Size.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @param {Object} params Params.
* @return {string} Request URL.
* @private
*/
ImageArcGISRest.prototype.getRequestUrl_ = function(extent, size, pixelRatio, projection, params) {
// ArcGIS Server only wants the numeric portion of the projection ID.
const srid = projection.getCode().split(':').pop();
params['SIZE'] = size[0] + ',' + size[1];
params['BBOX'] = extent.join(',');
params['BBOXSR'] = srid;
params['IMAGESR'] = srid;
params['DPI'] = Math.round(90 * pixelRatio);
const url = this.url_;
const modifiedUrl = url
.replace(/MapServer\/?$/, 'MapServer/export')
.replace(/ImageServer\/?$/, 'ImageServer/exportImage');
if (modifiedUrl == url) {
assert(false, 50); // `options.featureTypes` should be an Array
}
return appendParams(modifiedUrl, params);
};
/**
* Return the URL used for this ArcGIS source.
* @return {string|undefined} URL.
* @api
*/
ImageArcGISRest.prototype.getUrl = function() {
return this.url_;
};
/**
* Set the image load function of the source.
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
* @api
*/
ImageArcGISRest.prototype.setImageLoadFunction = function(imageLoadFunction) {
this.image_ = null;
this.imageLoadFunction_ = imageLoadFunction;
this.changed();
};
/**
* Set the URL to use for requests.
* @param {string|undefined} url URL.
* @api
*/
ImageArcGISRest.prototype.setUrl = function(url) {
if (url != this.url_) {
this.url_ = url;
this.image_ = null;
this.changed();
}
};
/**
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
ImageArcGISRest.prototype.updateParams = function(params) {
assign(this.params_, params);
this.image_ = null;
this.changed();
};
export default ImageArcGISRest;

View File

@@ -51,74 +51,77 @@ import ImageSource from '../source/Image.js';
* @param {module:ol/source/ImageCanvas~Options=} options ImageCanvas options.
* @api
*/
const ImageCanvasSource = function(options) {
class ImageCanvasSource {
constructor(options) {
ImageSource.call(this, {
attributions: options.attributions,
projection: options.projection,
resolutions: options.resolutions,
state: options.state
});
ImageSource.call(this, {
attributions: options.attributions,
projection: options.projection,
resolutions: options.resolutions,
state: options.state
});
/**
* @private
* @type {module:ol/source/ImageCanvas~FunctionType}
*/
this.canvasFunction_ = options.canvasFunction;
/**
* @private
* @type {module:ol/source/ImageCanvas~FunctionType}
*/
this.canvasFunction_ = options.canvasFunction;
/**
* @private
* @type {module:ol/ImageCanvas}
*/
this.canvas_ = null;
/**
* @private
* @type {module:ol/ImageCanvas}
*/
this.canvas_ = null;
/**
* @private
* @type {number}
*/
this.renderedRevision_ = 0;
/**
* @private
* @type {number}
*/
this.renderedRevision_ = 0;
/**
* @private
* @type {number}
*/
this.ratio_ = options.ratio !== undefined ?
options.ratio : 1.5;
/**
* @private
* @type {number}
*/
this.ratio_ = options.ratio !== undefined ?
options.ratio : 1.5;
};
}
/**
* @inheritDoc
*/
getImageInternal(extent, resolution, pixelRatio, projection) {
resolution = this.findNearestResolution(resolution);
let canvas = this.canvas_;
if (canvas &&
this.renderedRevision_ == this.getRevision() &&
canvas.getResolution() == resolution &&
canvas.getPixelRatio() == pixelRatio &&
containsExtent(canvas.getExtent(), extent)) {
return canvas;
}
extent = extent.slice();
scaleFromCenter(extent, this.ratio_);
const width = getWidth(extent) / resolution;
const height = getHeight(extent) / resolution;
const size = [width * pixelRatio, height * pixelRatio];
const canvasElement = this.canvasFunction_(
extent, resolution, pixelRatio, size, projection);
if (canvasElement) {
canvas = new ImageCanvas(extent, resolution, pixelRatio, canvasElement);
}
this.canvas_ = canvas;
this.renderedRevision_ = this.getRevision();
return canvas;
}
}
inherits(ImageCanvasSource, ImageSource);
/**
* @inheritDoc
*/
ImageCanvasSource.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
resolution = this.findNearestResolution(resolution);
let canvas = this.canvas_;
if (canvas &&
this.renderedRevision_ == this.getRevision() &&
canvas.getResolution() == resolution &&
canvas.getPixelRatio() == pixelRatio &&
containsExtent(canvas.getExtent(), extent)) {
return canvas;
}
extent = extent.slice();
scaleFromCenter(extent, this.ratio_);
const width = getWidth(extent) / resolution;
const height = getHeight(extent) / resolution;
const size = [width * pixelRatio, height * pixelRatio];
const canvasElement = this.canvasFunction_(
extent, resolution, pixelRatio, size, projection);
if (canvasElement) {
canvas = new ImageCanvas(extent, resolution, pixelRatio, canvasElement);
}
this.canvas_ = canvas;
this.renderedRevision_ = this.getRevision();
return canvas;
};
export default ImageCanvasSource;

View File

@@ -42,150 +42,199 @@ import {appendParams} from '../uri.js';
* @param {module:ol/source/ImageMapGuide~Options=} options ImageMapGuide options.
* @api
*/
const ImageMapGuide = function(options) {
class ImageMapGuide {
constructor(options) {
ImageSource.call(this, {
projection: options.projection,
resolutions: options.resolutions
});
ImageSource.call(this, {
projection: options.projection,
resolutions: options.resolutions
});
/**
* @private
* @type {?string}
*/
this.crossOrigin_ =
options.crossOrigin !== undefined ? options.crossOrigin : null;
/**
* @private
* @type {number}
*/
this.displayDpi_ = options.displayDpi !== undefined ?
options.displayDpi : 96;
/**
* @private
* @type {!Object}
*/
this.params_ = options.params || {};
/**
* @private
* @type {string|undefined}
*/
this.url_ = options.url;
/**
* @private
* @type {module:ol/Image~LoadFunction}
*/
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
options.imageLoadFunction : defaultImageLoadFunction;
/**
* @private
* @type {boolean}
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
/**
* @private
* @type {number}
*/
this.metersPerUnit_ = options.metersPerUnit !== undefined ?
options.metersPerUnit : 1;
/**
* @private
* @type {number}
*/
this.ratio_ = options.ratio !== undefined ? options.ratio : 1;
/**
* @private
* @type {boolean}
*/
this.useOverlay_ = options.useOverlay !== undefined ?
options.useOverlay : false;
/**
* @private
* @type {module:ol/Image}
*/
this.image_ = null;
/**
* @private
* @type {number}
*/
this.renderedRevision_ = 0;
}
/**
* @private
* @type {?string}
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
this.crossOrigin_ =
options.crossOrigin !== undefined ? options.crossOrigin : null;
getParams() {
return this.params_;
}
/**
* @private
* @type {number}
* @inheritDoc
*/
this.displayDpi_ = options.displayDpi !== undefined ?
options.displayDpi : 96;
getImageInternal(extent, resolution, pixelRatio, projection) {
resolution = this.findNearestResolution(resolution);
pixelRatio = this.hidpi_ ? pixelRatio : 1;
/**
* @private
* @type {!Object}
*/
this.params_ = options.params || {};
let image = this.image_;
if (image &&
this.renderedRevision_ == this.getRevision() &&
image.getResolution() == resolution &&
image.getPixelRatio() == pixelRatio &&
containsExtent(image.getExtent(), extent)) {
return image;
}
/**
* @private
* @type {string|undefined}
*/
this.url_ = options.url;
if (this.ratio_ != 1) {
extent = extent.slice();
scaleFromCenter(extent, this.ratio_);
}
const width = getWidth(extent) / resolution;
const height = getHeight(extent) / resolution;
const size = [width * pixelRatio, height * pixelRatio];
/**
* @private
* @type {module:ol/Image~LoadFunction}
*/
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
options.imageLoadFunction : defaultImageLoadFunction;
if (this.url_ !== undefined) {
const imageUrl = this.getUrl(this.url_, this.params_, extent, size,
projection);
image = new ImageWrapper(extent, resolution, pixelRatio,
imageUrl, this.crossOrigin_,
this.imageLoadFunction_);
listen(image, EventType.CHANGE,
this.handleImageChange, this);
} else {
image = null;
}
this.image_ = image;
this.renderedRevision_ = this.getRevision();
/**
* @private
* @type {boolean}
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
/**
* @private
* @type {number}
*/
this.metersPerUnit_ = options.metersPerUnit !== undefined ?
options.metersPerUnit : 1;
/**
* @private
* @type {number}
*/
this.ratio_ = options.ratio !== undefined ? options.ratio : 1;
/**
* @private
* @type {boolean}
*/
this.useOverlay_ = options.useOverlay !== undefined ?
options.useOverlay : false;
/**
* @private
* @type {module:ol/Image}
*/
this.image_ = null;
/**
* @private
* @type {number}
*/
this.renderedRevision_ = 0;
};
inherits(ImageMapGuide, ImageSource);
/**
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
ImageMapGuide.prototype.getParams = function() {
return this.params_;
};
/**
* @inheritDoc
*/
ImageMapGuide.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
resolution = this.findNearestResolution(resolution);
pixelRatio = this.hidpi_ ? pixelRatio : 1;
let image = this.image_;
if (image &&
this.renderedRevision_ == this.getRevision() &&
image.getResolution() == resolution &&
image.getPixelRatio() == pixelRatio &&
containsExtent(image.getExtent(), extent)) {
return image;
}
if (this.ratio_ != 1) {
extent = extent.slice();
scaleFromCenter(extent, this.ratio_);
/**
* Return the image load function of the source.
* @return {module:ol/Image~LoadFunction} The image load function.
* @api
*/
getImageLoadFunction() {
return this.imageLoadFunction_;
}
const width = getWidth(extent) / resolution;
const height = getHeight(extent) / resolution;
const size = [width * pixelRatio, height * pixelRatio];
if (this.url_ !== undefined) {
const imageUrl = this.getUrl(this.url_, this.params_, extent, size,
projection);
image = new ImageWrapper(extent, resolution, pixelRatio,
imageUrl, this.crossOrigin_,
this.imageLoadFunction_);
listen(image, EventType.CHANGE,
this.handleImageChange, this);
} else {
image = null;
/**
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
updateParams(params) {
assign(this.params_, params);
this.changed();
}
this.image_ = image;
this.renderedRevision_ = this.getRevision();
return image;
};
/**
* @param {string} baseUrl The mapagent url.
* @param {Object.<string, string|number>} params Request parameters.
* @param {module:ol/extent~Extent} extent Extent.
* @param {module:ol/size~Size} size Size.
* @param {module:ol/proj/Projection} projection Projection.
* @return {string} The mapagent map image request URL.
*/
getUrl(baseUrl, params, extent, size, projection) {
const scale = getScale(extent, size,
this.metersPerUnit_, this.displayDpi_);
const center = getCenter(extent);
const baseParams = {
'OPERATION': this.useOverlay_ ? 'GETDYNAMICMAPOVERLAYIMAGE' : 'GETMAPIMAGE',
'VERSION': '2.0.0',
'LOCALE': 'en',
'CLIENTAGENT': 'ol/source/ImageMapGuide source',
'CLIP': '1',
'SETDISPLAYDPI': this.displayDpi_,
'SETDISPLAYWIDTH': Math.round(size[0]),
'SETDISPLAYHEIGHT': Math.round(size[1]),
'SETVIEWSCALE': scale,
'SETVIEWCENTERX': center[0],
'SETVIEWCENTERY': center[1]
};
assign(baseParams, params);
return appendParams(baseUrl, baseParams);
}
/**
* Set the image load function of the MapGuide source.
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
* @api
*/
setImageLoadFunction(imageLoadFunction) {
this.image_ = null;
this.imageLoadFunction_ = imageLoadFunction;
this.changed();
}
}
/**
* Return the image load function of the source.
* @return {module:ol/Image~LoadFunction} The image load function.
* @api
*/
ImageMapGuide.prototype.getImageLoadFunction = function() {
return this.imageLoadFunction_;
};
inherits(ImageMapGuide, ImageSource);
/**
@@ -209,55 +258,4 @@ function getScale(extent, size, metersPerUnit, dpi) {
}
/**
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
ImageMapGuide.prototype.updateParams = function(params) {
assign(this.params_, params);
this.changed();
};
/**
* @param {string} baseUrl The mapagent url.
* @param {Object.<string, string|number>} params Request parameters.
* @param {module:ol/extent~Extent} extent Extent.
* @param {module:ol/size~Size} size Size.
* @param {module:ol/proj/Projection} projection Projection.
* @return {string} The mapagent map image request URL.
*/
ImageMapGuide.prototype.getUrl = function(baseUrl, params, extent, size, projection) {
const scale = getScale(extent, size,
this.metersPerUnit_, this.displayDpi_);
const center = getCenter(extent);
const baseParams = {
'OPERATION': this.useOverlay_ ? 'GETDYNAMICMAPOVERLAYIMAGE' : 'GETMAPIMAGE',
'VERSION': '2.0.0',
'LOCALE': 'en',
'CLIENTAGENT': 'ol/source/ImageMapGuide source',
'CLIP': '1',
'SETDISPLAYDPI': this.displayDpi_,
'SETDISPLAYWIDTH': Math.round(size[0]),
'SETDISPLAYHEIGHT': Math.round(size[1]),
'SETVIEWSCALE': scale,
'SETVIEWCENTERX': center[0],
'SETVIEWCENTERY': center[1]
};
assign(baseParams, params);
return appendParams(baseUrl, baseParams);
};
/**
* Set the image load function of the MapGuide source.
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
* @api
*/
ImageMapGuide.prototype.setImageLoadFunction = function(imageLoadFunction) {
this.image_ = null;
this.imageLoadFunction_ = imageLoadFunction;
this.changed();
};
export default ImageMapGuide;

View File

@@ -37,77 +37,79 @@ import ImageSource, {defaultImageLoadFunction} from '../source/Image.js';
* @param {module:ol/source/ImageStatic~Options=} options ImageStatic options.
* @api
*/
const Static = function(options) {
const imageExtent = options.imageExtent;
class Static {
constructor(options) {
const imageExtent = options.imageExtent;
const crossOrigin = options.crossOrigin !== undefined ?
options.crossOrigin : null;
const crossOrigin = options.crossOrigin !== undefined ?
options.crossOrigin : null;
const /** @type {module:ol/Image~LoadFunction} */ imageLoadFunction =
options.imageLoadFunction !== undefined ?
options.imageLoadFunction : defaultImageLoadFunction;
const /** @type {module:ol/Image~LoadFunction} */ imageLoadFunction =
options.imageLoadFunction !== undefined ?
options.imageLoadFunction : defaultImageLoadFunction;
ImageSource.call(this, {
attributions: options.attributions,
projection: getProjection(options.projection)
});
ImageSource.call(this, {
attributions: options.attributions,
projection: getProjection(options.projection)
});
/**
* @private
* @type {module:ol/Image}
*/
this.image_ = new ImageWrapper(imageExtent, undefined, 1, options.url, crossOrigin, imageLoadFunction);
/**
* @private
* @type {module:ol/size~Size}
*/
this.imageSize_ = options.imageSize ? options.imageSize : null;
listen(this.image_, EventType.CHANGE,
this.handleImageChange, this);
}
/**
* @private
* @type {module:ol/Image}
* @inheritDoc
*/
this.image_ = new ImageWrapper(imageExtent, undefined, 1, options.url, crossOrigin, imageLoadFunction);
getImageInternal(extent, resolution, pixelRatio, projection) {
if (intersects(extent, this.image_.getExtent())) {
return this.image_;
}
return null;
}
/**
* @private
* @type {module:ol/size~Size}
* @inheritDoc
*/
this.imageSize_ = options.imageSize ? options.imageSize : null;
listen(this.image_, EventType.CHANGE,
this.handleImageChange, this);
};
handleImageChange(evt) {
if (this.image_.getState() == ImageState.LOADED) {
const imageExtent = this.image_.getExtent();
const image = this.image_.getImage();
let imageWidth, imageHeight;
if (this.imageSize_) {
imageWidth = this.imageSize_[0];
imageHeight = this.imageSize_[1];
} else {
imageWidth = image.width;
imageHeight = image.height;
}
const resolution = getHeight(imageExtent) / imageHeight;
const targetWidth = Math.ceil(getWidth(imageExtent) / resolution);
if (targetWidth != imageWidth) {
const context = createCanvasContext2D(targetWidth, imageHeight);
const canvas = context.canvas;
context.drawImage(image, 0, 0, imageWidth, imageHeight,
0, 0, canvas.width, canvas.height);
this.image_.setImage(canvas);
}
}
ImageSource.prototype.handleImageChange.call(this, evt);
}
}
inherits(Static, ImageSource);
/**
* @inheritDoc
*/
Static.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
if (intersects(extent, this.image_.getExtent())) {
return this.image_;
}
return null;
};
/**
* @inheritDoc
*/
Static.prototype.handleImageChange = function(evt) {
if (this.image_.getState() == ImageState.LOADED) {
const imageExtent = this.image_.getExtent();
const image = this.image_.getImage();
let imageWidth, imageHeight;
if (this.imageSize_) {
imageWidth = this.imageSize_[0];
imageHeight = this.imageSize_[1];
} else {
imageWidth = image.width;
imageHeight = image.height;
}
const resolution = getHeight(imageExtent) / imageHeight;
const targetWidth = Math.ceil(getWidth(imageExtent) / resolution);
if (targetWidth != imageWidth) {
const context = createCanvasContext2D(targetWidth, imageHeight);
const canvas = context.canvas;
context.drawImage(image, 0, 0, imageWidth, imageHeight,
0, 0, canvas.width, canvas.height);
this.image_.setImage(canvas);
}
}
ImageSource.prototype.handleImageChange.call(this, evt);
};
export default Static;

View File

@@ -53,86 +53,329 @@ import {appendParams} from '../uri.js';
* @param {module:ol/source/ImageWMS~Options=} [opt_options] ImageWMS options.
* @api
*/
const ImageWMS = function(opt_options) {
class ImageWMS {
constructor(opt_options) {
const options = opt_options || {};
const options = opt_options || {};
ImageSource.call(this, {
attributions: options.attributions,
projection: options.projection,
resolutions: options.resolutions
});
ImageSource.call(this, {
attributions: options.attributions,
projection: options.projection,
resolutions: options.resolutions
});
/**
* @private
* @type {?string}
*/
this.crossOrigin_ =
options.crossOrigin !== undefined ? options.crossOrigin : null;
/**
* @private
* @type {string|undefined}
*/
this.url_ = options.url;
/**
* @private
* @type {module:ol/Image~LoadFunction}
*/
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
options.imageLoadFunction : defaultImageLoadFunction;
/**
* @private
* @type {!Object}
*/
this.params_ = options.params || {};
/**
* @private
* @type {boolean}
*/
this.v13_ = true;
this.updateV13_();
/**
* @private
* @type {module:ol/source/WMSServerType|undefined}
*/
this.serverType_ = /** @type {module:ol/source/WMSServerType|undefined} */ (options.serverType);
/**
* @private
* @type {boolean}
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
/**
* @private
* @type {module:ol/Image}
*/
this.image_ = null;
/**
* @private
* @type {module:ol/size~Size}
*/
this.imageSize_ = [0, 0];
/**
* @private
* @type {number}
*/
this.renderedRevision_ = 0;
/**
* @private
* @type {number}
*/
this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
}
/**
* Return the GetFeatureInfo URL for the passed coordinate, resolution, and
* projection. Return `undefined` if the GetFeatureInfo URL cannot be
* constructed.
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
* @param {number} resolution Resolution.
* @param {module:ol/proj~ProjectionLike} projection Projection.
* @param {!Object} params GetFeatureInfo params. `INFO_FORMAT` at least should
* be provided. If `QUERY_LAYERS` is not provided then the layers specified
* in the `LAYERS` parameter will be used. `VERSION` should not be
* specified here.
* @return {string|undefined} GetFeatureInfo URL.
* @api
*/
getGetFeatureInfoUrl(coordinate, resolution, projection, params) {
if (this.url_ === undefined) {
return undefined;
}
const projectionObj = getProjection(projection);
const sourceProjectionObj = this.getProjection();
if (sourceProjectionObj && sourceProjectionObj !== projectionObj) {
resolution = calculateSourceResolution(sourceProjectionObj, projectionObj, coordinate, resolution);
coordinate = transform(coordinate, projectionObj, sourceProjectionObj);
}
const extent = getForViewAndSize(coordinate, resolution, 0,
GETFEATUREINFO_IMAGE_SIZE);
const baseParams = {
'SERVICE': 'WMS',
'VERSION': DEFAULT_WMS_VERSION,
'REQUEST': 'GetFeatureInfo',
'FORMAT': 'image/png',
'TRANSPARENT': true,
'QUERY_LAYERS': this.params_['LAYERS']
};
assign(baseParams, this.params_, params);
const x = Math.floor((coordinate[0] - extent[0]) / resolution);
const y = Math.floor((extent[3] - coordinate[1]) / resolution);
baseParams[this.v13_ ? 'I' : 'X'] = x;
baseParams[this.v13_ ? 'J' : 'Y'] = y;
return this.getRequestUrl_(
extent, GETFEATUREINFO_IMAGE_SIZE,
1, sourceProjectionObj || projectionObj, baseParams);
}
/**
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
getParams() {
return this.params_;
}
/**
* @inheritDoc
*/
getImageInternal(extent, resolution, pixelRatio, projection) {
if (this.url_ === undefined) {
return null;
}
resolution = this.findNearestResolution(resolution);
if (pixelRatio != 1 && (!this.hidpi_ || this.serverType_ === undefined)) {
pixelRatio = 1;
}
const imageResolution = resolution / pixelRatio;
const center = getCenter(extent);
const viewWidth = Math.ceil(getWidth(extent) / imageResolution);
const viewHeight = Math.ceil(getHeight(extent) / imageResolution);
const viewExtent = getForViewAndSize(center, imageResolution, 0,
[viewWidth, viewHeight]);
const requestWidth = Math.ceil(this.ratio_ * getWidth(extent) / imageResolution);
const requestHeight = Math.ceil(this.ratio_ * getHeight(extent) / imageResolution);
const requestExtent = getForViewAndSize(center, imageResolution, 0,
[requestWidth, requestHeight]);
const image = this.image_;
if (image &&
this.renderedRevision_ == this.getRevision() &&
image.getResolution() == resolution &&
image.getPixelRatio() == pixelRatio &&
containsExtent(image.getExtent(), viewExtent)) {
return image;
}
const params = {
'SERVICE': 'WMS',
'VERSION': DEFAULT_WMS_VERSION,
'REQUEST': 'GetMap',
'FORMAT': 'image/png',
'TRANSPARENT': true
};
assign(params, this.params_);
this.imageSize_[0] = Math.round(getWidth(requestExtent) / imageResolution);
this.imageSize_[1] = Math.round(getHeight(requestExtent) / imageResolution);
const url = this.getRequestUrl_(requestExtent, this.imageSize_, pixelRatio,
projection, params);
this.image_ = new ImageWrapper(requestExtent, resolution, pixelRatio,
url, this.crossOrigin_, this.imageLoadFunction_);
this.renderedRevision_ = this.getRevision();
listen(this.image_, EventType.CHANGE,
this.handleImageChange, this);
return this.image_;
}
/**
* Return the image load function of the source.
* @return {module:ol/Image~LoadFunction} The image load function.
* @api
*/
getImageLoadFunction() {
return this.imageLoadFunction_;
}
/**
* @param {module:ol/extent~Extent} extent Extent.
* @param {module:ol/size~Size} size Size.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @param {Object} params Params.
* @return {string} Request URL.
* @private
*/
getRequestUrl_(extent, size, pixelRatio, projection, params) {
assert(this.url_ !== undefined, 9); // `url` must be configured or set using `#setUrl()`
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
if (!('STYLES' in this.params_)) {
params['STYLES'] = '';
}
if (pixelRatio != 1) {
switch (this.serverType_) {
case WMSServerType.GEOSERVER:
const dpi = (90 * pixelRatio + 0.5) | 0;
if ('FORMAT_OPTIONS' in params) {
params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
} else {
params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
}
break;
case WMSServerType.MAPSERVER:
params['MAP_RESOLUTION'] = 90 * pixelRatio;
break;
case WMSServerType.CARMENTA_SERVER:
case WMSServerType.QGIS:
params['DPI'] = 90 * pixelRatio;
break;
default:
assert(false, 8); // Unknown `serverType` configured
break;
}
}
params['WIDTH'] = size[0];
params['HEIGHT'] = size[1];
const axisOrientation = projection.getAxisOrientation();
let bbox;
if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {
bbox = [extent[1], extent[0], extent[3], extent[2]];
} else {
bbox = extent;
}
params['BBOX'] = bbox.join(',');
return appendParams(/** @type {string} */ (this.url_), params);
}
/**
* Return the URL used for this WMS source.
* @return {string|undefined} URL.
* @api
*/
getUrl() {
return this.url_;
}
/**
* Set the image load function of the source.
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
* @api
*/
setImageLoadFunction(imageLoadFunction) {
this.image_ = null;
this.imageLoadFunction_ = imageLoadFunction;
this.changed();
}
/**
* Set the URL to use for requests.
* @param {string|undefined} url URL.
* @api
*/
setUrl(url) {
if (url != this.url_) {
this.url_ = url;
this.image_ = null;
this.changed();
}
}
/**
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
updateParams(params) {
assign(this.params_, params);
this.updateV13_();
this.image_ = null;
this.changed();
}
/**
* @private
* @type {?string}
*/
this.crossOrigin_ =
options.crossOrigin !== undefined ? options.crossOrigin : null;
/**
* @private
* @type {string|undefined}
*/
this.url_ = options.url;
/**
* @private
* @type {module:ol/Image~LoadFunction}
*/
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
options.imageLoadFunction : defaultImageLoadFunction;
/**
* @private
* @type {!Object}
*/
this.params_ = options.params || {};
/**
* @private
* @type {boolean}
*/
this.v13_ = true;
this.updateV13_();
/**
* @private
* @type {module:ol/source/WMSServerType|undefined}
*/
this.serverType_ = /** @type {module:ol/source/WMSServerType|undefined} */ (options.serverType);
/**
* @private
* @type {boolean}
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
/**
* @private
* @type {module:ol/Image}
*/
this.image_ = null;
/**
* @private
* @type {module:ol/size~Size}
*/
this.imageSize_ = [0, 0];
/**
* @private
* @type {number}
*/
this.renderedRevision_ = 0;
/**
* @private
* @type {number}
*/
this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
};
updateV13_() {
const version = this.params_['VERSION'] || DEFAULT_WMS_VERSION;
this.v13_ = compareVersions(version, '1.3') >= 0;
}
}
inherits(ImageWMS, ImageSource);
@@ -144,253 +387,4 @@ inherits(ImageWMS, ImageSource);
const GETFEATUREINFO_IMAGE_SIZE = [101, 101];
/**
* Return the GetFeatureInfo URL for the passed coordinate, resolution, and
* projection. Return `undefined` if the GetFeatureInfo URL cannot be
* constructed.
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
* @param {number} resolution Resolution.
* @param {module:ol/proj~ProjectionLike} projection Projection.
* @param {!Object} params GetFeatureInfo params. `INFO_FORMAT` at least should
* be provided. If `QUERY_LAYERS` is not provided then the layers specified
* in the `LAYERS` parameter will be used. `VERSION` should not be
* specified here.
* @return {string|undefined} GetFeatureInfo URL.
* @api
*/
ImageWMS.prototype.getGetFeatureInfoUrl = function(coordinate, resolution, projection, params) {
if (this.url_ === undefined) {
return undefined;
}
const projectionObj = getProjection(projection);
const sourceProjectionObj = this.getProjection();
if (sourceProjectionObj && sourceProjectionObj !== projectionObj) {
resolution = calculateSourceResolution(sourceProjectionObj, projectionObj, coordinate, resolution);
coordinate = transform(coordinate, projectionObj, sourceProjectionObj);
}
const extent = getForViewAndSize(coordinate, resolution, 0,
GETFEATUREINFO_IMAGE_SIZE);
const baseParams = {
'SERVICE': 'WMS',
'VERSION': DEFAULT_WMS_VERSION,
'REQUEST': 'GetFeatureInfo',
'FORMAT': 'image/png',
'TRANSPARENT': true,
'QUERY_LAYERS': this.params_['LAYERS']
};
assign(baseParams, this.params_, params);
const x = Math.floor((coordinate[0] - extent[0]) / resolution);
const y = Math.floor((extent[3] - coordinate[1]) / resolution);
baseParams[this.v13_ ? 'I' : 'X'] = x;
baseParams[this.v13_ ? 'J' : 'Y'] = y;
return this.getRequestUrl_(
extent, GETFEATUREINFO_IMAGE_SIZE,
1, sourceProjectionObj || projectionObj, baseParams);
};
/**
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
ImageWMS.prototype.getParams = function() {
return this.params_;
};
/**
* @inheritDoc
*/
ImageWMS.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
if (this.url_ === undefined) {
return null;
}
resolution = this.findNearestResolution(resolution);
if (pixelRatio != 1 && (!this.hidpi_ || this.serverType_ === undefined)) {
pixelRatio = 1;
}
const imageResolution = resolution / pixelRatio;
const center = getCenter(extent);
const viewWidth = Math.ceil(getWidth(extent) / imageResolution);
const viewHeight = Math.ceil(getHeight(extent) / imageResolution);
const viewExtent = getForViewAndSize(center, imageResolution, 0,
[viewWidth, viewHeight]);
const requestWidth = Math.ceil(this.ratio_ * getWidth(extent) / imageResolution);
const requestHeight = Math.ceil(this.ratio_ * getHeight(extent) / imageResolution);
const requestExtent = getForViewAndSize(center, imageResolution, 0,
[requestWidth, requestHeight]);
const image = this.image_;
if (image &&
this.renderedRevision_ == this.getRevision() &&
image.getResolution() == resolution &&
image.getPixelRatio() == pixelRatio &&
containsExtent(image.getExtent(), viewExtent)) {
return image;
}
const params = {
'SERVICE': 'WMS',
'VERSION': DEFAULT_WMS_VERSION,
'REQUEST': 'GetMap',
'FORMAT': 'image/png',
'TRANSPARENT': true
};
assign(params, this.params_);
this.imageSize_[0] = Math.round(getWidth(requestExtent) / imageResolution);
this.imageSize_[1] = Math.round(getHeight(requestExtent) / imageResolution);
const url = this.getRequestUrl_(requestExtent, this.imageSize_, pixelRatio,
projection, params);
this.image_ = new ImageWrapper(requestExtent, resolution, pixelRatio,
url, this.crossOrigin_, this.imageLoadFunction_);
this.renderedRevision_ = this.getRevision();
listen(this.image_, EventType.CHANGE,
this.handleImageChange, this);
return this.image_;
};
/**
* Return the image load function of the source.
* @return {module:ol/Image~LoadFunction} The image load function.
* @api
*/
ImageWMS.prototype.getImageLoadFunction = function() {
return this.imageLoadFunction_;
};
/**
* @param {module:ol/extent~Extent} extent Extent.
* @param {module:ol/size~Size} size Size.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @param {Object} params Params.
* @return {string} Request URL.
* @private
*/
ImageWMS.prototype.getRequestUrl_ = function(extent, size, pixelRatio, projection, params) {
assert(this.url_ !== undefined, 9); // `url` must be configured or set using `#setUrl()`
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
if (!('STYLES' in this.params_)) {
params['STYLES'] = '';
}
if (pixelRatio != 1) {
switch (this.serverType_) {
case WMSServerType.GEOSERVER:
const dpi = (90 * pixelRatio + 0.5) | 0;
if ('FORMAT_OPTIONS' in params) {
params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
} else {
params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
}
break;
case WMSServerType.MAPSERVER:
params['MAP_RESOLUTION'] = 90 * pixelRatio;
break;
case WMSServerType.CARMENTA_SERVER:
case WMSServerType.QGIS:
params['DPI'] = 90 * pixelRatio;
break;
default:
assert(false, 8); // Unknown `serverType` configured
break;
}
}
params['WIDTH'] = size[0];
params['HEIGHT'] = size[1];
const axisOrientation = projection.getAxisOrientation();
let bbox;
if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {
bbox = [extent[1], extent[0], extent[3], extent[2]];
} else {
bbox = extent;
}
params['BBOX'] = bbox.join(',');
return appendParams(/** @type {string} */ (this.url_), params);
};
/**
* Return the URL used for this WMS source.
* @return {string|undefined} URL.
* @api
*/
ImageWMS.prototype.getUrl = function() {
return this.url_;
};
/**
* Set the image load function of the source.
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
* @api
*/
ImageWMS.prototype.setImageLoadFunction = function(imageLoadFunction) {
this.image_ = null;
this.imageLoadFunction_ = imageLoadFunction;
this.changed();
};
/**
* Set the URL to use for requests.
* @param {string|undefined} url URL.
* @api
*/
ImageWMS.prototype.setUrl = function(url) {
if (url != this.url_) {
this.url_ = url;
this.image_ = null;
this.changed();
}
};
/**
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
ImageWMS.prototype.updateParams = function(params) {
assign(this.params_, params);
this.updateV13_();
this.image_ = null;
this.changed();
};
/**
* @private
*/
ImageWMS.prototype.updateV13_ = function() {
const version = this.params_['VERSION'] || DEFAULT_WMS_VERSION;
this.v13_ = compareVersions(version, '1.3') >= 0;
};
export default ImageWMS;

View File

@@ -144,276 +144,279 @@ inherits(RasterSourceEvent, Event);
* @param {module:ol/source/Raster~Options=} options Options.
* @api
*/
const RasterSource = function(options) {
class RasterSource {
constructor(options) {
/**
* @private
* @type {*}
*/
this.worker_ = null;
/**
* @private
* @type {*}
*/
this.worker_ = null;
/**
* @private
* @type {module:ol/source/Raster~RasterOperationType}
*/
this.operationType_ = options.operationType !== undefined ?
options.operationType : RasterOperationType.PIXEL;
/**
* @private
* @type {module:ol/source/Raster~RasterOperationType}
*/
this.operationType_ = options.operationType !== undefined ?
options.operationType : RasterOperationType.PIXEL;
/**
* @private
* @type {number}
*/
this.threads_ = options.threads !== undefined ? options.threads : 1;
/**
* @private
* @type {number}
*/
this.threads_ = options.threads !== undefined ? options.threads : 1;
/**
* @private
* @type {Array.<module:ol/renderer/canvas/Layer>}
*/
this.renderers_ = createRenderers(options.sources);
/**
* @private
* @type {Array.<module:ol/renderer/canvas/Layer>}
*/
this.renderers_ = createRenderers(options.sources);
for (let r = 0, rr = this.renderers_.length; r < rr; ++r) {
listen(this.renderers_[r], EventType.CHANGE,
this.changed, this);
}
/**
* @private
* @type {module:ol/TileQueue}
*/
this.tileQueue_ = new TileQueue(
function() {
return 1;
},
this.changed.bind(this));
const layerStatesArray = getLayerStatesArray(this.renderers_);
const layerStates = {};
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
layerStates[getUid(layerStatesArray[i].layer)] = layerStatesArray[i];
}
/**
* The most recently requested frame state.
* @type {module:ol/PluggableMap~FrameState}
* @private
*/
this.requestedFrameState_;
/**
* The most recently rendered image canvas.
* @type {module:ol/ImageCanvas}
* @private
*/
this.renderedImageCanvas_ = null;
/**
* The most recently rendered revision.
* @type {number}
*/
this.renderedRevision_;
/**
* @private
* @type {module:ol/PluggableMap~FrameState}
*/
this.frameState_ = {
animate: false,
coordinateToPixelTransform: createTransform(),
extent: null,
focus: null,
index: 0,
layerStates: layerStates,
layerStatesArray: layerStatesArray,
pixelRatio: 1,
pixelToCoordinateTransform: createTransform(),
postRenderFunctions: [],
size: [0, 0],
skippedFeatureUids: {},
tileQueue: this.tileQueue_,
time: Date.now(),
usedTiles: {},
viewState: /** @type {module:ol/View~State} */ ({
rotation: 0
}),
viewHints: [],
wantedTiles: {}
};
ImageSource.call(this, {});
if (options.operation !== undefined) {
this.setOperation(options.operation, options.lib);
}
};
inherits(RasterSource, ImageSource);
/**
* Set the operation.
* @param {module:ol/source/Raster~Operation} operation New operation.
* @param {Object=} opt_lib Functions that will be available to operations run
* in a worker.
* @api
*/
RasterSource.prototype.setOperation = function(operation, opt_lib) {
this.worker_ = new Processor({
operation: operation,
imageOps: this.operationType_ === RasterOperationType.IMAGE,
queue: 1,
lib: opt_lib,
threads: this.threads_
});
this.changed();
};
/**
* Update the stored frame state.
* @param {module:ol/extent~Extent} extent The view extent (in map units).
* @param {number} resolution The view resolution.
* @param {module:ol/proj/Projection} projection The view projection.
* @return {module:ol/PluggableMap~FrameState} The updated frame state.
* @private
*/
RasterSource.prototype.updateFrameState_ = function(extent, resolution, projection) {
const frameState = /** @type {module:ol/PluggableMap~FrameState} */ (assign({}, this.frameState_));
frameState.viewState = /** @type {module:ol/View~State} */ (assign({}, frameState.viewState));
const center = getCenter(extent);
frameState.extent = extent.slice();
frameState.focus = center;
frameState.size[0] = Math.round(getWidth(extent) / resolution);
frameState.size[1] = Math.round(getHeight(extent) / resolution);
frameState.time = Date.now();
frameState.animate = false;
const viewState = frameState.viewState;
viewState.center = center;
viewState.projection = projection;
viewState.resolution = resolution;
return frameState;
};
/**
* Determine if all sources are ready.
* @return {boolean} All sources are ready.
* @private
*/
RasterSource.prototype.allSourcesReady_ = function() {
let ready = true;
let source;
for (let i = 0, ii = this.renderers_.length; i < ii; ++i) {
source = this.renderers_[i].getLayer().getSource();
if (source.getState() !== SourceState.READY) {
ready = false;
break;
for (let r = 0, rr = this.renderers_.length; r < rr; ++r) {
listen(this.renderers_[r], EventType.CHANGE,
this.changed, this);
}
}
return ready;
};
/**
* @private
* @type {module:ol/TileQueue}
*/
this.tileQueue_ = new TileQueue(
function() {
return 1;
},
this.changed.bind(this));
/**
* @inheritDoc
*/
RasterSource.prototype.getImage = function(extent, resolution, pixelRatio, projection) {
if (!this.allSourcesReady_()) {
return null;
}
const frameState = this.updateFrameState_(extent, resolution, projection);
this.requestedFrameState_ = frameState;
// check if we can't reuse the existing ol/ImageCanvas
if (this.renderedImageCanvas_) {
const renderedResolution = this.renderedImageCanvas_.getResolution();
const renderedExtent = this.renderedImageCanvas_.getExtent();
if (resolution !== renderedResolution || !equals(extent, renderedExtent)) {
this.renderedImageCanvas_ = null;
const layerStatesArray = getLayerStatesArray(this.renderers_);
const layerStates = {};
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
layerStates[getUid(layerStatesArray[i].layer)] = layerStatesArray[i];
}
/**
* The most recently requested frame state.
* @type {module:ol/PluggableMap~FrameState}
* @private
*/
this.requestedFrameState_;
/**
* The most recently rendered image canvas.
* @type {module:ol/ImageCanvas}
* @private
*/
this.renderedImageCanvas_ = null;
/**
* The most recently rendered revision.
* @type {number}
*/
this.renderedRevision_;
/**
* @private
* @type {module:ol/PluggableMap~FrameState}
*/
this.frameState_ = {
animate: false,
coordinateToPixelTransform: createTransform(),
extent: null,
focus: null,
index: 0,
layerStates: layerStates,
layerStatesArray: layerStatesArray,
pixelRatio: 1,
pixelToCoordinateTransform: createTransform(),
postRenderFunctions: [],
size: [0, 0],
skippedFeatureUids: {},
tileQueue: this.tileQueue_,
time: Date.now(),
usedTiles: {},
viewState: /** @type {module:ol/View~State} */ ({
rotation: 0
}),
viewHints: [],
wantedTiles: {}
};
ImageSource.call(this, {});
if (options.operation !== undefined) {
this.setOperation(options.operation, options.lib);
}
}
if (!this.renderedImageCanvas_ || this.getRevision() !== this.renderedRevision_) {
this.processSources_();
/**
* Set the operation.
* @param {module:ol/source/Raster~Operation} operation New operation.
* @param {Object=} opt_lib Functions that will be available to operations run
* in a worker.
* @api
*/
setOperation(operation, opt_lib) {
this.worker_ = new Processor({
operation: operation,
imageOps: this.operationType_ === RasterOperationType.IMAGE,
queue: 1,
lib: opt_lib,
threads: this.threads_
});
this.changed();
}
frameState.tileQueue.loadMoreTiles(16, 16);
/**
* Update the stored frame state.
* @param {module:ol/extent~Extent} extent The view extent (in map units).
* @param {number} resolution The view resolution.
* @param {module:ol/proj/Projection} projection The view projection.
* @return {module:ol/PluggableMap~FrameState} The updated frame state.
* @private
*/
updateFrameState_(extent, resolution, projection) {
if (frameState.animate) {
requestAnimationFrame(this.changed.bind(this));
const frameState = /** @type {module:ol/PluggableMap~FrameState} */ (assign({}, this.frameState_));
frameState.viewState = /** @type {module:ol/View~State} */ (assign({}, frameState.viewState));
const center = getCenter(extent);
frameState.extent = extent.slice();
frameState.focus = center;
frameState.size[0] = Math.round(getWidth(extent) / resolution);
frameState.size[1] = Math.round(getHeight(extent) / resolution);
frameState.time = Date.now();
frameState.animate = false;
const viewState = frameState.viewState;
viewState.center = center;
viewState.projection = projection;
viewState.resolution = resolution;
return frameState;
}
return this.renderedImageCanvas_;
};
/**
* Determine if all sources are ready.
* @return {boolean} All sources are ready.
* @private
*/
allSourcesReady_() {
let ready = true;
let source;
for (let i = 0, ii = this.renderers_.length; i < ii; ++i) {
source = this.renderers_[i].getLayer().getSource();
if (source.getState() !== SourceState.READY) {
ready = false;
break;
}
}
return ready;
}
/**
* @inheritDoc
*/
getImage(extent, resolution, pixelRatio, projection) {
if (!this.allSourcesReady_()) {
return null;
}
/**
* Start processing source data.
* @private
*/
RasterSource.prototype.processSources_ = function() {
const frameState = this.requestedFrameState_;
const len = this.renderers_.length;
const imageDatas = new Array(len);
for (let i = 0; i < len; ++i) {
const imageData = getImageData(
this.renderers_[i], frameState, frameState.layerStatesArray[i]);
if (imageData) {
imageDatas[i] = imageData;
} else {
const frameState = this.updateFrameState_(extent, resolution, projection);
this.requestedFrameState_ = frameState;
// check if we can't reuse the existing ol/ImageCanvas
if (this.renderedImageCanvas_) {
const renderedResolution = this.renderedImageCanvas_.getResolution();
const renderedExtent = this.renderedImageCanvas_.getExtent();
if (resolution !== renderedResolution || !equals(extent, renderedExtent)) {
this.renderedImageCanvas_ = null;
}
}
if (!this.renderedImageCanvas_ || this.getRevision() !== this.renderedRevision_) {
this.processSources_();
}
frameState.tileQueue.loadMoreTiles(16, 16);
if (frameState.animate) {
requestAnimationFrame(this.changed.bind(this));
}
return this.renderedImageCanvas_;
}
/**
* Start processing source data.
* @private
*/
processSources_() {
const frameState = this.requestedFrameState_;
const len = this.renderers_.length;
const imageDatas = new Array(len);
for (let i = 0; i < len; ++i) {
const imageData = getImageData(
this.renderers_[i], frameState, frameState.layerStatesArray[i]);
if (imageData) {
imageDatas[i] = imageData;
} else {
return;
}
}
const data = {};
this.dispatchEvent(new RasterSourceEvent(RasterEventType.BEFOREOPERATIONS, frameState, data));
this.worker_.process(imageDatas, data, this.onWorkerComplete_.bind(this, frameState));
}
/**
* Called when pixel processing is complete.
* @param {module:ol/PluggableMap~FrameState} frameState The frame state.
* @param {Error} err Any error during processing.
* @param {ImageData} output The output image data.
* @param {Object} data The user data.
* @private
*/
onWorkerComplete_(frameState, err, output, data) {
if (err || !output) {
return;
}
// do nothing if extent or resolution changed
const extent = frameState.extent;
const resolution = frameState.viewState.resolution;
if (resolution !== this.requestedFrameState_.viewState.resolution ||
!equals(extent, this.requestedFrameState_.extent)) {
return;
}
let context;
if (this.renderedImageCanvas_) {
context = this.renderedImageCanvas_.getImage().getContext('2d');
} else {
const width = Math.round(getWidth(extent) / resolution);
const height = Math.round(getHeight(extent) / resolution);
context = createCanvasContext2D(width, height);
this.renderedImageCanvas_ = new ImageCanvas(extent, resolution, 1, context.canvas);
}
context.putImageData(output, 0, 0);
this.changed();
this.renderedRevision_ = this.getRevision();
this.dispatchEvent(new RasterSourceEvent(RasterEventType.AFTEROPERATIONS, frameState, data));
}
const data = {};
this.dispatchEvent(new RasterSourceEvent(RasterEventType.BEFOREOPERATIONS, frameState, data));
this.worker_.process(imageDatas, data, this.onWorkerComplete_.bind(this, frameState));
};
/**
* Called when pixel processing is complete.
* @param {module:ol/PluggableMap~FrameState} frameState The frame state.
* @param {Error} err Any error during processing.
* @param {ImageData} output The output image data.
* @param {Object} data The user data.
* @private
*/
RasterSource.prototype.onWorkerComplete_ = function(frameState, err, output, data) {
if (err || !output) {
return;
/**
* @override
*/
getImageInternal() {
return null; // not implemented
}
}
// do nothing if extent or resolution changed
const extent = frameState.extent;
const resolution = frameState.viewState.resolution;
if (resolution !== this.requestedFrameState_.viewState.resolution ||
!equals(extent, this.requestedFrameState_.extent)) {
return;
}
let context;
if (this.renderedImageCanvas_) {
context = this.renderedImageCanvas_.getImage().getContext('2d');
} else {
const width = Math.round(getWidth(extent) / resolution);
const height = Math.round(getHeight(extent) / resolution);
context = createCanvasContext2D(width, height);
this.renderedImageCanvas_ = new ImageCanvas(extent, resolution, 1, context.canvas);
}
context.putImageData(output, 0, 0);
this.changed();
this.renderedRevision_ = this.getRevision();
this.dispatchEvent(new RasterSourceEvent(RasterEventType.AFTEROPERATIONS, frameState, data));
};
inherits(RasterSource, ImageSource);
/**
@@ -522,12 +525,4 @@ function createTileRenderer(source) {
}
/**
* @override
*/
RasterSource.prototype.getImageInternal = function() {
return null; // not implemented
};
export default RasterSource;

View File

@@ -51,63 +51,134 @@ import SourceState from '../source/State.js';
* @param {module:ol/source/Source~Options} options Source options.
* @api
*/
const Source = function(options) {
class Source {
constructor(options) {
BaseObject.call(this);
BaseObject.call(this);
/**
* @private
* @type {module:ol/proj/Projection}
*/
this.projection_ = getProjection(options.projection);
/**
* @private
* @type {module:ol/proj/Projection}
*/
this.projection_ = getProjection(options.projection);
/**
* @private
* @type {?module:ol/source/Source~Attribution}
*/
this.attributions_ = this.adaptAttributions_(options.attributions);
/**
* @private
* @type {?module:ol/source/Source~Attribution}
*/
this.attributions_ = this.adaptAttributions_(options.attributions);
/**
* @private
* @type {module:ol/source/State}
*/
this.state_ = options.state !== undefined ?
options.state : SourceState.READY;
/**
* @private
* @type {module:ol/source/State}
*/
this.state_ = options.state !== undefined ?
options.state : SourceState.READY;
/**
* @private
* @type {boolean}
*/
this.wrapX_ = options.wrapX !== undefined ? options.wrapX : false;
/**
* @private
* @type {boolean}
*/
this.wrapX_ = options.wrapX !== undefined ? options.wrapX : false;
};
}
/**
* Turns the attributions option into an attributions function.
* @param {module:ol/source/Source~AttributionLike|undefined} attributionLike The attribution option.
* @return {?module:ol/source/Source~Attribution} An attribution function (or null).
*/
adaptAttributions_(attributionLike) {
if (!attributionLike) {
return null;
}
if (Array.isArray(attributionLike)) {
return function(frameState) {
return attributionLike;
};
}
if (typeof attributionLike === 'function') {
return attributionLike;
}
return function(frameState) {
return [attributionLike];
};
}
/**
* Get the attribution function for the source.
* @return {?module:ol/source/Source~Attribution} Attribution function.
*/
getAttributions() {
return this.attributions_;
}
/**
* Get the projection of the source.
* @return {module:ol/proj/Projection} Projection.
* @api
*/
getProjection() {
return this.projection_;
}
/**
* @abstract
* @return {Array.<number>|undefined} Resolutions.
*/
getResolutions() {}
/**
* Get the state of the source, see {@link module:ol/source/State~State} for possible states.
* @return {module:ol/source/State} State.
* @api
*/
getState() {
return this.state_;
}
/**
* @return {boolean|undefined} Wrap X.
*/
getWrapX() {
return this.wrapX_;
}
/**
* Refreshes the source and finally dispatches a 'change' event.
* @api
*/
refresh() {
this.changed();
}
/**
* Set the attributions of the source.
* @param {module:ol/source/Source~AttributionLike|undefined} attributions Attributions.
* Can be passed as `string`, `Array<string>`, `{@link module:ol/source/Source~Attribution}`,
* or `undefined`.
* @api
*/
setAttributions(attributions) {
this.attributions_ = this.adaptAttributions_(attributions);
this.changed();
}
/**
* Set the state of the source.
* @param {module:ol/source/State} state State.
* @protected
*/
setState(state) {
this.state_ = state;
this.changed();
}
}
inherits(Source, BaseObject);
/**
* Turns the attributions option into an attributions function.
* @param {module:ol/source/Source~AttributionLike|undefined} attributionLike The attribution option.
* @return {?module:ol/source/Source~Attribution} An attribution function (or null).
*/
Source.prototype.adaptAttributions_ = function(attributionLike) {
if (!attributionLike) {
return null;
}
if (Array.isArray(attributionLike)) {
return function(frameState) {
return attributionLike;
};
}
if (typeof attributionLike === 'function') {
return attributionLike;
}
return function(frameState) {
return [attributionLike];
};
};
/**
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
* @param {number} resolution Resolution.
@@ -121,79 +192,4 @@ Source.prototype.adaptAttributions_ = function(attributionLike) {
Source.prototype.forEachFeatureAtCoordinate = UNDEFINED;
/**
* Get the attribution function for the source.
* @return {?module:ol/source/Source~Attribution} Attribution function.
*/
Source.prototype.getAttributions = function() {
return this.attributions_;
};
/**
* Get the projection of the source.
* @return {module:ol/proj/Projection} Projection.
* @api
*/
Source.prototype.getProjection = function() {
return this.projection_;
};
/**
* @abstract
* @return {Array.<number>|undefined} Resolutions.
*/
Source.prototype.getResolutions = function() {};
/**
* Get the state of the source, see {@link module:ol/source/State~State} for possible states.
* @return {module:ol/source/State} State.
* @api
*/
Source.prototype.getState = function() {
return this.state_;
};
/**
* @return {boolean|undefined} Wrap X.
*/
Source.prototype.getWrapX = function() {
return this.wrapX_;
};
/**
* Refreshes the source and finally dispatches a 'change' event.
* @api
*/
Source.prototype.refresh = function() {
this.changed();
};
/**
* Set the attributions of the source.
* @param {module:ol/source/Source~AttributionLike|undefined} attributions Attributions.
* Can be passed as `string`, `Array<string>`, `{@link module:ol/source/Source~Attribution}`,
* or `undefined`.
* @api
*/
Source.prototype.setAttributions = function(attributions) {
this.attributions_ = this.adaptAttributions_(attributions);
this.changed();
};
/**
* Set the state of the source.
* @param {module:ol/source/State} state State.
* @protected
*/
Source.prototype.setState = function(state) {
this.state_ = state;
this.changed();
};
export default Source;

View File

@@ -39,277 +39,263 @@ import {wrapX, getForProjection as getTileGridForProjection} from '../tilegrid.j
* @param {module:ol/source/Tile~Options=} options SourceTile source options.
* @api
*/
const TileSource = function(options) {
class TileSource {
constructor(options) {
Source.call(this, {
attributions: options.attributions,
extent: options.extent,
projection: options.projection,
state: options.state,
wrapX: options.wrapX
});
Source.call(this, {
attributions: options.attributions,
extent: options.extent,
projection: options.projection,
state: options.state,
wrapX: options.wrapX
});
/**
* @private
* @type {boolean}
*/
this.opaque_ = options.opaque !== undefined ? options.opaque : false;
/**
* @private
* @type {boolean}
*/
this.opaque_ = options.opaque !== undefined ? options.opaque : false;
/**
* @private
* @type {number}
*/
this.tilePixelRatio_ = options.tilePixelRatio !== undefined ?
options.tilePixelRatio : 1;
/**
* @private
* @type {number}
*/
this.tilePixelRatio_ = options.tilePixelRatio !== undefined ?
options.tilePixelRatio : 1;
/**
* @protected
* @type {module:ol/tilegrid/TileGrid}
*/
this.tileGrid = options.tileGrid !== undefined ? options.tileGrid : null;
/**
* @protected
* @type {module:ol/tilegrid/TileGrid}
*/
this.tileGrid = options.tileGrid !== undefined ? options.tileGrid : null;
/**
* @protected
* @type {module:ol/TileCache}
*/
this.tileCache = new TileCache(options.cacheSize);
/**
* @protected
* @type {module:ol/TileCache}
*/
this.tileCache = new TileCache(options.cacheSize);
/**
* @protected
* @type {module:ol/size~Size}
*/
this.tmpSize = [0, 0];
/**
* @protected
* @type {module:ol/size~Size}
*/
this.tmpSize = [0, 0];
/**
* @private
* @type {string}
*/
this.key_ = '';
/**
* @private
* @type {string}
*/
this.key_ = '';
/**
* @protected
* @type {module:ol/Tile~Options}
*/
this.tileOptions = {transition: options.transition};
/**
* @protected
* @type {module:ol/Tile~Options}
*/
this.tileOptions = {transition: options.transition};
};
inherits(TileSource, Source);
/**
* @return {boolean} Can expire cache.
*/
TileSource.prototype.canExpireCache = function() {
return this.tileCache.canExpireCache();
};
/**
* @param {module:ol/proj/Projection} projection Projection.
* @param {!Object.<string, module:ol/TileRange>} usedTiles Used tiles.
*/
TileSource.prototype.expireCache = function(projection, usedTiles) {
const tileCache = this.getTileCacheForProjection(projection);
if (tileCache) {
tileCache.expireCache(usedTiles);
}
};
/**
* @param {module:ol/proj/Projection} projection Projection.
* @param {number} z Zoom level.
* @param {module:ol/TileRange} tileRange Tile range.
* @param {function(module:ol/Tile):(boolean|undefined)} callback Called with each
* loaded tile. If the callback returns `false`, the tile will not be
* considered loaded.
* @return {boolean} The tile range is fully covered with loaded tiles.
*/
TileSource.prototype.forEachLoadedTile = function(projection, z, tileRange, callback) {
const tileCache = this.getTileCacheForProjection(projection);
if (!tileCache) {
return false;
}
let covered = true;
let tile, tileCoordKey, loaded;
for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (let y = tileRange.minY; y <= tileRange.maxY; ++y) {
tileCoordKey = getKeyZXY(z, x, y);
loaded = false;
if (tileCache.containsKey(tileCoordKey)) {
tile = /** @type {!module:ol/Tile} */ (tileCache.get(tileCoordKey));
loaded = tile.getState() === TileState.LOADED;
if (loaded) {
loaded = (callback(tile) !== false);
}
}
if (!loaded) {
covered = false;
}
/**
* @return {boolean} Can expire cache.
*/
canExpireCache() {
return this.tileCache.canExpireCache();
}
/**
* @param {module:ol/proj/Projection} projection Projection.
* @param {!Object.<string, module:ol/TileRange>} usedTiles Used tiles.
*/
expireCache(projection, usedTiles) {
const tileCache = this.getTileCacheForProjection(projection);
if (tileCache) {
tileCache.expireCache(usedTiles);
}
}
return covered;
};
/**
* @param {module:ol/proj/Projection} projection Projection.
* @param {number} z Zoom level.
* @param {module:ol/TileRange} tileRange Tile range.
* @param {function(module:ol/Tile):(boolean|undefined)} callback Called with each
* loaded tile. If the callback returns `false`, the tile will not be
* considered loaded.
* @return {boolean} The tile range is fully covered with loaded tiles.
*/
forEachLoadedTile(projection, z, tileRange, callback) {
const tileCache = this.getTileCacheForProjection(projection);
if (!tileCache) {
return false;
}
/**
* @param {module:ol/proj/Projection} projection Projection.
* @return {number} Gutter.
*/
TileSource.prototype.getGutter = function(projection) {
return 0;
};
/**
* Return the key to be used for all tiles in the source.
* @return {string} The key for all tiles.
* @protected
*/
TileSource.prototype.getKey = function() {
return this.key_;
};
/**
* Set the value to be used as the key for all tiles in the source.
* @param {string} key The key for tiles.
* @protected
*/
TileSource.prototype.setKey = function(key) {
if (this.key_ !== key) {
this.key_ = key;
this.changed();
let covered = true;
let tile, tileCoordKey, loaded;
for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (let y = tileRange.minY; y <= tileRange.maxY; ++y) {
tileCoordKey = getKeyZXY(z, x, y);
loaded = false;
if (tileCache.containsKey(tileCoordKey)) {
tile = /** @type {!module:ol/Tile} */ (tileCache.get(tileCoordKey));
loaded = tile.getState() === TileState.LOADED;
if (loaded) {
loaded = (callback(tile) !== false);
}
}
if (!loaded) {
covered = false;
}
}
}
return covered;
}
};
/**
* @param {module:ol/proj/Projection} projection Projection.
* @return {number} Gutter.
*/
getGutter(projection) {
return 0;
}
/**
* @param {module:ol/proj/Projection} projection Projection.
* @return {boolean} Opaque.
*/
TileSource.prototype.getOpaque = function(projection) {
return this.opaque_;
};
/**
* Return the key to be used for all tiles in the source.
* @return {string} The key for all tiles.
* @protected
*/
getKey() {
return this.key_;
}
/**
* Set the value to be used as the key for all tiles in the source.
* @param {string} key The key for tiles.
* @protected
*/
setKey(key) {
if (this.key_ !== key) {
this.key_ = key;
this.changed();
}
}
/**
* @inheritDoc
*/
TileSource.prototype.getResolutions = function() {
return this.tileGrid.getResolutions();
};
/**
* @param {module:ol/proj/Projection} projection Projection.
* @return {boolean} Opaque.
*/
getOpaque(projection) {
return this.opaque_;
}
/**
* @inheritDoc
*/
getResolutions() {
return this.tileGrid.getResolutions();
}
/**
* @abstract
* @param {number} z Tile coordinate z.
* @param {number} x Tile coordinate x.
* @param {number} y Tile coordinate y.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @return {!module:ol/Tile} Tile.
*/
TileSource.prototype.getTile = function(z, x, y, pixelRatio, projection) {};
/**
* @abstract
* @param {number} z Tile coordinate z.
* @param {number} x Tile coordinate x.
* @param {number} y Tile coordinate y.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @return {!module:ol/Tile} Tile.
*/
getTile(z, x, y, pixelRatio, projection) {}
/**
* Return the tile grid of the tile source.
* @return {module:ol/tilegrid/TileGrid} Tile grid.
* @api
*/
TileSource.prototype.getTileGrid = function() {
return this.tileGrid;
};
/**
* @param {module:ol/proj/Projection} projection Projection.
* @return {!module:ol/tilegrid/TileGrid} Tile grid.
*/
TileSource.prototype.getTileGridForProjection = function(projection) {
if (!this.tileGrid) {
return getTileGridForProjection(projection);
} else {
/**
* Return the tile grid of the tile source.
* @return {module:ol/tilegrid/TileGrid} Tile grid.
* @api
*/
getTileGrid() {
return this.tileGrid;
}
};
/**
* @param {module:ol/proj/Projection} projection Projection.
* @return {module:ol/TileCache} Tile cache.
* @protected
*/
TileSource.prototype.getTileCacheForProjection = function(projection) {
const thisProj = this.getProjection();
if (thisProj && !equivalent(thisProj, projection)) {
return null;
} else {
return this.tileCache;
/**
* @param {module:ol/proj/Projection} projection Projection.
* @return {!module:ol/tilegrid/TileGrid} Tile grid.
*/
getTileGridForProjection(projection) {
if (!this.tileGrid) {
return getTileGridForProjection(projection);
} else {
return this.tileGrid;
}
}
};
/**
* Get the tile pixel ratio for this source. Subclasses may override this
* method, which is meant to return a supported pixel ratio that matches the
* provided `pixelRatio` as close as possible.
* @param {number} pixelRatio Pixel ratio.
* @return {number} Tile pixel ratio.
*/
TileSource.prototype.getTilePixelRatio = function(pixelRatio) {
return this.tilePixelRatio_;
};
/**
* @param {number} z Z.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @return {module:ol/size~Size} Tile size.
*/
TileSource.prototype.getTilePixelSize = function(z, pixelRatio, projection) {
const tileGrid = this.getTileGridForProjection(projection);
const tilePixelRatio = this.getTilePixelRatio(pixelRatio);
const tileSize = toSize(tileGrid.getTileSize(z), this.tmpSize);
if (tilePixelRatio == 1) {
return tileSize;
} else {
return scaleSize(tileSize, tilePixelRatio, this.tmpSize);
/**
* @param {module:ol/proj/Projection} projection Projection.
* @return {module:ol/TileCache} Tile cache.
* @protected
*/
getTileCacheForProjection(projection) {
const thisProj = this.getProjection();
if (thisProj && !equivalent(thisProj, projection)) {
return null;
} else {
return this.tileCache;
}
}
};
/**
* Returns a tile coordinate wrapped around the x-axis. When the tile coordinate
* is outside the resolution and extent range of the tile grid, `null` will be
* returned.
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
* @param {module:ol/proj/Projection=} opt_projection Projection.
* @return {module:ol/tilecoord~TileCoord} Tile coordinate to be passed to the tileUrlFunction or
* null if no tile URL should be created for the passed `tileCoord`.
*/
TileSource.prototype.getTileCoordForTileUrlFunction = function(tileCoord, opt_projection) {
const projection = opt_projection !== undefined ?
opt_projection : this.getProjection();
const tileGrid = this.getTileGridForProjection(projection);
if (this.getWrapX() && projection.isGlobal()) {
tileCoord = wrapX(tileGrid, tileCoord, projection);
/**
* Get the tile pixel ratio for this source. Subclasses may override this
* method, which is meant to return a supported pixel ratio that matches the
* provided `pixelRatio` as close as possible.
* @param {number} pixelRatio Pixel ratio.
* @return {number} Tile pixel ratio.
*/
getTilePixelRatio(pixelRatio) {
return this.tilePixelRatio_;
}
return withinExtentAndZ(tileCoord, tileGrid) ? tileCoord : null;
};
/**
* @param {number} z Z.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @return {module:ol/size~Size} Tile size.
*/
getTilePixelSize(z, pixelRatio, projection) {
const tileGrid = this.getTileGridForProjection(projection);
const tilePixelRatio = this.getTilePixelRatio(pixelRatio);
const tileSize = toSize(tileGrid.getTileSize(z), this.tmpSize);
if (tilePixelRatio == 1) {
return tileSize;
} else {
return scaleSize(tileSize, tilePixelRatio, this.tmpSize);
}
}
/**
* @inheritDoc
*/
TileSource.prototype.refresh = function() {
this.tileCache.clear();
this.changed();
};
/**
* Returns a tile coordinate wrapped around the x-axis. When the tile coordinate
* is outside the resolution and extent range of the tile grid, `null` will be
* returned.
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
* @param {module:ol/proj/Projection=} opt_projection Projection.
* @return {module:ol/tilecoord~TileCoord} Tile coordinate to be passed to the tileUrlFunction or
* null if no tile URL should be created for the passed `tileCoord`.
*/
getTileCoordForTileUrlFunction(tileCoord, opt_projection) {
const projection = opt_projection !== undefined ?
opt_projection : this.getProjection();
const tileGrid = this.getTileGridForProjection(projection);
if (this.getWrapX() && projection.isGlobal()) {
tileCoord = wrapX(tileGrid, tileCoord, projection);
}
return withinExtentAndZ(tileCoord, tileGrid) ? tileCoord : null;
}
/**
* @inheritDoc
*/
refresh() {
this.tileCache.clear();
this.changed();
}
}
inherits(TileSource, Source);
/**

View File

@@ -64,162 +64,159 @@ import {appendParams} from '../uri.js';
* @param {module:ol/source/TileArcGISRest~Options=} opt_options Tile ArcGIS Rest options.
* @api
*/
const TileArcGISRest = function(opt_options) {
class TileArcGISRest {
constructor(opt_options) {
const options = opt_options || {};
const options = opt_options || {};
TileImage.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
projection: options.projection,
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction,
url: options.url,
urls: options.urls,
wrapX: options.wrapX !== undefined ? options.wrapX : true,
transition: options.transition
});
TileImage.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
projection: options.projection,
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction,
url: options.url,
urls: options.urls,
wrapX: options.wrapX !== undefined ? options.wrapX : true,
transition: options.transition
});
/**
* @private
* @type {!Object}
*/
this.params_ = options.params || {};
/**
* @private
* @type {module:ol/extent~Extent}
*/
this.tmpExtent_ = createEmpty();
this.setKey(this.getKeyForParams_());
}
/**
* @private
* @type {!Object}
* @return {string} The key for the current params.
*/
this.params_ = options.params || {};
getKeyForParams_() {
let i = 0;
const res = [];
for (const key in this.params_) {
res[i++] = key + '-' + this.params_[key];
}
return res.join('/');
}
/**
* @private
* @type {module:ol/extent~Extent}
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
this.tmpExtent_ = createEmpty();
getParams() {
return this.params_;
}
this.setKey(this.getKeyForParams_());
};
/**
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
* @param {module:ol/size~Size} tileSize Tile size.
* @param {module:ol/extent~Extent} tileExtent Tile extent.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @param {Object} params Params.
* @return {string|undefined} Request URL.
* @private
*/
getRequestUrl_(tileCoord, tileSize, tileExtent, pixelRatio, projection, params) {
const urls = this.urls;
if (!urls) {
return undefined;
}
// ArcGIS Server only wants the numeric portion of the projection ID.
const srid = projection.getCode().split(':').pop();
params['SIZE'] = tileSize[0] + ',' + tileSize[1];
params['BBOX'] = tileExtent.join(',');
params['BBOXSR'] = srid;
params['IMAGESR'] = srid;
params['DPI'] = Math.round(
params['DPI'] ? params['DPI'] * pixelRatio : 90 * pixelRatio
);
let url;
if (urls.length == 1) {
url = urls[0];
} else {
const index = modulo(tileCoordHash(tileCoord), urls.length);
url = urls[index];
}
const modifiedUrl = url
.replace(/MapServer\/?$/, 'MapServer/export')
.replace(/ImageServer\/?$/, 'ImageServer/exportImage');
return appendParams(modifiedUrl, params);
}
/**
* @inheritDoc
*/
getTilePixelRatio(pixelRatio) {
return /** @type {number} */ (pixelRatio);
}
/**
* @inheritDoc
*/
fixedTileUrlFunction(tileCoord, pixelRatio, projection) {
let tileGrid = this.getTileGrid();
if (!tileGrid) {
tileGrid = this.getTileGridForProjection(projection);
}
if (tileGrid.getResolutions().length <= tileCoord[0]) {
return undefined;
}
const tileExtent = tileGrid.getTileCoordExtent(
tileCoord, this.tmpExtent_);
let tileSize = toSize(
tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
if (pixelRatio != 1) {
tileSize = scaleSize(tileSize, pixelRatio, this.tmpSize);
}
// Apply default params and override with user specified values.
const baseParams = {
'F': 'image',
'FORMAT': 'PNG32',
'TRANSPARENT': true
};
assign(baseParams, this.params_);
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
pixelRatio, projection, baseParams);
}
/**
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
updateParams(params) {
assign(this.params_, params);
this.setKey(this.getKeyForParams_());
}
}
inherits(TileArcGISRest, TileImage);
/**
* @private
* @return {string} The key for the current params.
*/
TileArcGISRest.prototype.getKeyForParams_ = function() {
let i = 0;
const res = [];
for (const key in this.params_) {
res[i++] = key + '-' + this.params_[key];
}
return res.join('/');
};
/**
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
TileArcGISRest.prototype.getParams = function() {
return this.params_;
};
/**
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
* @param {module:ol/size~Size} tileSize Tile size.
* @param {module:ol/extent~Extent} tileExtent Tile extent.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @param {Object} params Params.
* @return {string|undefined} Request URL.
* @private
*/
TileArcGISRest.prototype.getRequestUrl_ = function(tileCoord, tileSize, tileExtent,
pixelRatio, projection, params) {
const urls = this.urls;
if (!urls) {
return undefined;
}
// ArcGIS Server only wants the numeric portion of the projection ID.
const srid = projection.getCode().split(':').pop();
params['SIZE'] = tileSize[0] + ',' + tileSize[1];
params['BBOX'] = tileExtent.join(',');
params['BBOXSR'] = srid;
params['IMAGESR'] = srid;
params['DPI'] = Math.round(
params['DPI'] ? params['DPI'] * pixelRatio : 90 * pixelRatio
);
let url;
if (urls.length == 1) {
url = urls[0];
} else {
const index = modulo(tileCoordHash(tileCoord), urls.length);
url = urls[index];
}
const modifiedUrl = url
.replace(/MapServer\/?$/, 'MapServer/export')
.replace(/ImageServer\/?$/, 'ImageServer/exportImage');
return appendParams(modifiedUrl, params);
};
/**
* @inheritDoc
*/
TileArcGISRest.prototype.getTilePixelRatio = function(pixelRatio) {
return /** @type {number} */ (pixelRatio);
};
/**
* @inheritDoc
*/
TileArcGISRest.prototype.fixedTileUrlFunction = function(tileCoord, pixelRatio, projection) {
let tileGrid = this.getTileGrid();
if (!tileGrid) {
tileGrid = this.getTileGridForProjection(projection);
}
if (tileGrid.getResolutions().length <= tileCoord[0]) {
return undefined;
}
const tileExtent = tileGrid.getTileCoordExtent(
tileCoord, this.tmpExtent_);
let tileSize = toSize(
tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
if (pixelRatio != 1) {
tileSize = scaleSize(tileSize, pixelRatio, this.tmpSize);
}
// Apply default params and override with user specified values.
const baseParams = {
'F': 'image',
'FORMAT': 'PNG32',
'TRANSPARENT': true
};
assign(baseParams, this.params_);
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
pixelRatio, projection, baseParams);
};
/**
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
TileArcGISRest.prototype.updateParams = function(params) {
assign(this.params_, params);
this.setKey(this.getKeyForParams_());
};
export default TileArcGISRest;

View File

@@ -17,64 +17,65 @@ import {getKeyZXY} from '../tilecoord.js';
* @param {module:ol/size~Size} tileSize Tile size.
* @param {string} text Text.
*/
const LabeledTile = function(tileCoord, tileSize, text) {
class LabeledTile {
constructor(tileCoord, tileSize, text) {
Tile.call(this, tileCoord, TileState.LOADED);
Tile.call(this, tileCoord, TileState.LOADED);
/**
* @private
* @type {module:ol/size~Size}
*/
this.tileSize_ = tileSize;
/**
* @private
* @type {module:ol/size~Size}
*/
this.tileSize_ = tileSize;
/**
* @private
* @type {string}
*/
this.text_ = text;
/**
* @private
* @type {string}
*/
this.text_ = text;
/**
* @private
* @type {HTMLCanvasElement}
*/
this.canvas_ = null;
/**
* @private
* @type {HTMLCanvasElement}
*/
this.canvas_ = null;
}
/**
* Get the image element for this tile.
* @return {HTMLCanvasElement} Image.
*/
getImage() {
if (this.canvas_) {
return this.canvas_;
} else {
const tileSize = this.tileSize_;
const context = createCanvasContext2D(tileSize[0], tileSize[1]);
context.strokeStyle = 'black';
context.strokeRect(0.5, 0.5, tileSize[0] + 0.5, tileSize[1] + 0.5);
context.fillStyle = 'black';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.font = '24px sans-serif';
context.fillText(this.text_, tileSize[0] / 2, tileSize[1] / 2);
this.canvas_ = context.canvas;
return context.canvas;
}
}
/**
* @override
*/
load() {}
}
};
inherits(LabeledTile, Tile);
/**
* Get the image element for this tile.
* @return {HTMLCanvasElement} Image.
*/
LabeledTile.prototype.getImage = function() {
if (this.canvas_) {
return this.canvas_;
} else {
const tileSize = this.tileSize_;
const context = createCanvasContext2D(tileSize[0], tileSize[1]);
context.strokeStyle = 'black';
context.strokeRect(0.5, 0.5, tileSize[0] + 0.5, tileSize[1] + 0.5);
context.fillStyle = 'black';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.font = '24px sans-serif';
context.fillText(this.text_, tileSize[0] / 2, tileSize[1] / 2);
this.canvas_ = context.canvas;
return context.canvas;
}
};
/**
* @override
*/
LabeledTile.prototype.load = function() {};
/**
* @typedef {Object} Options
* @property {module:ol/proj~ProjectionLike} projection Projection.
@@ -96,38 +97,39 @@ LabeledTile.prototype.load = function() {};
* @param {module:ol/source/TileDebug~Options=} options Debug tile options.
* @api
*/
const TileDebug = function(options) {
class TileDebug {
constructor(options) {
TileSource.call(this, {
opaque: false,
projection: options.projection,
tileGrid: options.tileGrid,
wrapX: options.wrapX !== undefined ? options.wrapX : true
});
TileSource.call(this, {
opaque: false,
projection: options.projection,
tileGrid: options.tileGrid,
wrapX: options.wrapX !== undefined ? options.wrapX : true
});
};
}
/**
* @inheritDoc
*/
getTile(z, x, y) {
const tileCoordKey = getKeyZXY(z, x, y);
if (this.tileCache.containsKey(tileCoordKey)) {
return /** @type {!module:ol/source/TileDebug~LabeledTile} */ (this.tileCache.get(tileCoordKey));
} else {
const tileSize = toSize(this.tileGrid.getTileSize(z));
const tileCoord = [z, x, y];
const textTileCoord = this.getTileCoordForTileUrlFunction(tileCoord);
const text = !textTileCoord ? '' :
this.getTileCoordForTileUrlFunction(textTileCoord).toString();
const tile = new LabeledTile(tileCoord, tileSize, text);
this.tileCache.set(tileCoordKey, tile);
return tile;
}
}
}
inherits(TileDebug, TileSource);
/**
* @inheritDoc
*/
TileDebug.prototype.getTile = function(z, x, y) {
const tileCoordKey = getKeyZXY(z, x, y);
if (this.tileCache.containsKey(tileCoordKey)) {
return /** @type {!module:ol/source/TileDebug~LabeledTile} */ (this.tileCache.get(tileCoordKey));
} else {
const tileSize = toSize(this.tileGrid.getTileSize(z));
const tileCoord = [z, x, y];
const textTileCoord = this.getTileCoordForTileUrlFunction(tileCoord);
const text = !textTileCoord ? '' :
this.getTileCoordForTileUrlFunction(textTileCoord).toString();
const tile = new LabeledTile(tileCoord, tileSize, text);
this.tileCache.set(tileCoordKey, tile);
return tile;
}
};
export default TileDebug;

View File

@@ -64,344 +64,334 @@ import {getForProjection as getTileGridForProjection} from '../tilegrid.js';
* @param {module:ol/source/TileImage~Options=} options Image tile options.
* @api
*/
const TileImage = function(options) {
class TileImage {
constructor(options) {
UrlTile.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
extent: options.extent,
opaque: options.opaque,
projection: options.projection,
state: options.state,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction ?
options.tileLoadFunction : defaultTileLoadFunction,
tilePixelRatio: options.tilePixelRatio,
tileUrlFunction: options.tileUrlFunction,
url: options.url,
urls: options.urls,
wrapX: options.wrapX,
transition: options.transition
});
UrlTile.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
extent: options.extent,
opaque: options.opaque,
projection: options.projection,
state: options.state,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction ?
options.tileLoadFunction : defaultTileLoadFunction,
tilePixelRatio: options.tilePixelRatio,
tileUrlFunction: options.tileUrlFunction,
url: options.url,
urls: options.urls,
wrapX: options.wrapX,
transition: options.transition
});
/**
* @protected
* @type {?string}
*/
this.crossOrigin =
options.crossOrigin !== undefined ? options.crossOrigin : null;
/**
* @protected
* @type {function(new: module:ol/ImageTile, module:ol/tilecoord~TileCoord, module:ol/TileState, string,
* ?string, module:ol/Tile~LoadFunction, module:ol/Tile~Options=)}
*/
this.tileClass = options.tileClass !== undefined ?
options.tileClass : ImageTile;
/**
* @protected
* @type {!Object.<string, module:ol/TileCache>}
*/
this.tileCacheForProjection = {};
/**
* @protected
* @type {!Object.<string, module:ol/tilegrid/TileGrid>}
*/
this.tileGridForProjection = {};
/**
* @private
* @type {number|undefined}
*/
this.reprojectionErrorThreshold_ = options.reprojectionErrorThreshold;
/**
* @private
* @type {boolean}
*/
this.renderReprojectionEdges_ = false;
}
/**
* @inheritDoc
*/
canExpireCache() {
if (!ENABLE_RASTER_REPROJECTION) {
return UrlTile.prototype.canExpireCache.call(this);
}
if (this.tileCache.canExpireCache()) {
return true;
} else {
for (const key in this.tileCacheForProjection) {
if (this.tileCacheForProjection[key].canExpireCache()) {
return true;
}
}
}
return false;
}
/**
* @inheritDoc
*/
expireCache(projection, usedTiles) {
if (!ENABLE_RASTER_REPROJECTION) {
UrlTile.prototype.expireCache.call(this, projection, usedTiles);
return;
}
const usedTileCache = this.getTileCacheForProjection(projection);
this.tileCache.expireCache(this.tileCache == usedTileCache ? usedTiles : {});
for (const id in this.tileCacheForProjection) {
const tileCache = this.tileCacheForProjection[id];
tileCache.expireCache(tileCache == usedTileCache ? usedTiles : {});
}
}
/**
* @inheritDoc
*/
getGutter(projection) {
if (ENABLE_RASTER_REPROJECTION &&
this.getProjection() && projection && !equivalent(this.getProjection(), projection)) {
return 0;
} else {
return this.getGutterInternal();
}
}
/**
* @protected
* @type {?string}
* @return {number} Gutter.
*/
this.crossOrigin =
options.crossOrigin !== undefined ? options.crossOrigin : null;
getGutterInternal() {
return 0;
}
/**
* @protected
* @type {function(new: module:ol/ImageTile, module:ol/tilecoord~TileCoord, module:ol/TileState, string,
* ?string, module:ol/Tile~LoadFunction, module:ol/Tile~Options=)}
* @inheritDoc
*/
this.tileClass = options.tileClass !== undefined ?
options.tileClass : ImageTile;
getOpaque(projection) {
if (ENABLE_RASTER_REPROJECTION &&
this.getProjection() && projection && !equivalent(this.getProjection(), projection)) {
return false;
} else {
return UrlTile.prototype.getOpaque.call(this, projection);
}
}
/**
* @protected
* @type {!Object.<string, module:ol/TileCache>}
* @inheritDoc
*/
this.tileCacheForProjection = {};
getTileGridForProjection(projection) {
if (!ENABLE_RASTER_REPROJECTION) {
return UrlTile.prototype.getTileGridForProjection.call(this, projection);
}
const thisProj = this.getProjection();
if (this.tileGrid && (!thisProj || equivalent(thisProj, projection))) {
return this.tileGrid;
} else {
const projKey = getUid(projection).toString();
if (!(projKey in this.tileGridForProjection)) {
this.tileGridForProjection[projKey] = getTileGridForProjection(projection);
}
return (
/** @type {!module:ol/tilegrid/TileGrid} */ (this.tileGridForProjection[projKey])
);
}
}
/**
* @protected
* @type {!Object.<string, module:ol/tilegrid/TileGrid>}
* @inheritDoc
*/
this.tileGridForProjection = {};
getTileCacheForProjection(projection) {
if (!ENABLE_RASTER_REPROJECTION) {
return UrlTile.prototype.getTileCacheForProjection.call(this, projection);
}
const thisProj = this.getProjection(); if (!thisProj || equivalent(thisProj, projection)) {
return this.tileCache;
} else {
const projKey = getUid(projection).toString();
if (!(projKey in this.tileCacheForProjection)) {
this.tileCacheForProjection[projKey] = new TileCache(this.tileCache.highWaterMark);
}
return this.tileCacheForProjection[projKey];
}
}
/**
* @param {number} z Tile coordinate z.
* @param {number} x Tile coordinate x.
* @param {number} y Tile coordinate y.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @param {string} key The key set on the tile.
* @return {!module:ol/Tile} Tile.
* @private
* @type {number|undefined}
*/
this.reprojectionErrorThreshold_ = options.reprojectionErrorThreshold;
createTile_(z, x, y, pixelRatio, projection, key) {
const tileCoord = [z, x, y];
const urlTileCoord = this.getTileCoordForTileUrlFunction(
tileCoord, projection);
const tileUrl = urlTileCoord ?
this.tileUrlFunction(urlTileCoord, pixelRatio, projection) : undefined;
const tile = new this.tileClass(
tileCoord,
tileUrl !== undefined ? TileState.IDLE : TileState.EMPTY,
tileUrl !== undefined ? tileUrl : '',
this.crossOrigin,
this.tileLoadFunction,
this.tileOptions);
tile.key = key;
listen(tile, EventType.CHANGE,
this.handleTileChange, this);
return tile;
}
/**
* @private
* @type {boolean}
* @inheritDoc
*/
this.renderReprojectionEdges_ = false;
};
getTile(z, x, y, pixelRatio, projection) {
const sourceProjection = /** @type {!module:ol/proj/Projection} */ (this.getProjection());
if (!ENABLE_RASTER_REPROJECTION ||
!sourceProjection || !projection || equivalent(sourceProjection, projection)) {
return this.getTileInternal(z, x, y, pixelRatio, sourceProjection || projection);
} else {
const cache = this.getTileCacheForProjection(projection);
const tileCoord = [z, x, y];
let tile;
const tileCoordKey = getKey(tileCoord);
if (cache.containsKey(tileCoordKey)) {
tile = /** @type {!module:ol/Tile} */ (cache.get(tileCoordKey));
}
const key = this.getKey();
if (tile && tile.key == key) {
return tile;
} else {
const sourceTileGrid = this.getTileGridForProjection(sourceProjection);
const targetTileGrid = this.getTileGridForProjection(projection);
const wrappedTileCoord =
this.getTileCoordForTileUrlFunction(tileCoord, projection);
const newTile = new ReprojTile(
sourceProjection, sourceTileGrid,
projection, targetTileGrid,
tileCoord, wrappedTileCoord, this.getTilePixelRatio(pixelRatio),
this.getGutterInternal(),
function(z, x, y, pixelRatio) {
return this.getTileInternal(z, x, y, pixelRatio, sourceProjection);
}.bind(this), this.reprojectionErrorThreshold_,
this.renderReprojectionEdges_);
newTile.key = key;
if (tile) {
newTile.interimTile = tile;
newTile.refreshInterimChain();
cache.replace(tileCoordKey, newTile);
} else {
cache.set(tileCoordKey, newTile);
}
return newTile;
}
}
}
/**
* @param {number} z Tile coordinate z.
* @param {number} x Tile coordinate x.
* @param {number} y Tile coordinate y.
* @param {number} pixelRatio Pixel ratio.
* @param {!module:ol/proj/Projection} projection Projection.
* @return {!module:ol/Tile} Tile.
* @protected
*/
getTileInternal(z, x, y, pixelRatio, projection) {
let tile = null;
const tileCoordKey = getKeyZXY(z, x, y);
const key = this.getKey();
if (!this.tileCache.containsKey(tileCoordKey)) {
tile = this.createTile_(z, x, y, pixelRatio, projection, key);
this.tileCache.set(tileCoordKey, tile);
} else {
tile = this.tileCache.get(tileCoordKey);
if (tile.key != key) {
// The source's params changed. If the tile has an interim tile and if we
// can use it then we use it. Otherwise we create a new tile. In both
// cases we attempt to assign an interim tile to the new tile.
const interimTile = tile;
tile = this.createTile_(z, x, y, pixelRatio, projection, key);
//make the new tile the head of the list,
if (interimTile.getState() == TileState.IDLE) {
//the old tile hasn't begun loading yet, and is now outdated, so we can simply discard it
tile.interimTile = interimTile.interimTile;
} else {
tile.interimTile = interimTile;
}
tile.refreshInterimChain();
this.tileCache.replace(tileCoordKey, tile);
}
}
return tile;
}
/**
* Sets whether to render reprojection edges or not (usually for debugging).
* @param {boolean} render Render the edges.
* @api
*/
setRenderReprojectionEdges(render) {
if (!ENABLE_RASTER_REPROJECTION ||
this.renderReprojectionEdges_ == render) {
return;
}
this.renderReprojectionEdges_ = render;
for (const id in this.tileCacheForProjection) {
this.tileCacheForProjection[id].clear();
}
this.changed();
}
/**
* Sets the tile grid to use when reprojecting the tiles to the given
* projection instead of the default tile grid for the projection.
*
* This can be useful when the default tile grid cannot be created
* (e.g. projection has no extent defined) or
* for optimization reasons (custom tile size, resolutions, ...).
*
* @param {module:ol/proj~ProjectionLike} projection Projection.
* @param {module:ol/tilegrid/TileGrid} tilegrid Tile grid to use for the projection.
* @api
*/
setTileGridForProjection(projection, tilegrid) {
if (ENABLE_RASTER_REPROJECTION) {
const proj = getProjection(projection);
if (proj) {
const projKey = getUid(proj).toString();
if (!(projKey in this.tileGridForProjection)) {
this.tileGridForProjection[projKey] = tilegrid;
}
}
}
}
}
inherits(TileImage, UrlTile);
/**
* @inheritDoc
*/
TileImage.prototype.canExpireCache = function() {
if (!ENABLE_RASTER_REPROJECTION) {
return UrlTile.prototype.canExpireCache.call(this);
}
if (this.tileCache.canExpireCache()) {
return true;
} else {
for (const key in this.tileCacheForProjection) {
if (this.tileCacheForProjection[key].canExpireCache()) {
return true;
}
}
}
return false;
};
/**
* @inheritDoc
*/
TileImage.prototype.expireCache = function(projection, usedTiles) {
if (!ENABLE_RASTER_REPROJECTION) {
UrlTile.prototype.expireCache.call(this, projection, usedTiles);
return;
}
const usedTileCache = this.getTileCacheForProjection(projection);
this.tileCache.expireCache(this.tileCache == usedTileCache ? usedTiles : {});
for (const id in this.tileCacheForProjection) {
const tileCache = this.tileCacheForProjection[id];
tileCache.expireCache(tileCache == usedTileCache ? usedTiles : {});
}
};
/**
* @inheritDoc
*/
TileImage.prototype.getGutter = function(projection) {
if (ENABLE_RASTER_REPROJECTION &&
this.getProjection() && projection && !equivalent(this.getProjection(), projection)) {
return 0;
} else {
return this.getGutterInternal();
}
};
/**
* @protected
* @return {number} Gutter.
*/
TileImage.prototype.getGutterInternal = function() {
return 0;
};
/**
* @inheritDoc
*/
TileImage.prototype.getOpaque = function(projection) {
if (ENABLE_RASTER_REPROJECTION &&
this.getProjection() && projection && !equivalent(this.getProjection(), projection)) {
return false;
} else {
return UrlTile.prototype.getOpaque.call(this, projection);
}
};
/**
* @inheritDoc
*/
TileImage.prototype.getTileGridForProjection = function(projection) {
if (!ENABLE_RASTER_REPROJECTION) {
return UrlTile.prototype.getTileGridForProjection.call(this, projection);
}
const thisProj = this.getProjection();
if (this.tileGrid && (!thisProj || equivalent(thisProj, projection))) {
return this.tileGrid;
} else {
const projKey = getUid(projection).toString();
if (!(projKey in this.tileGridForProjection)) {
this.tileGridForProjection[projKey] = getTileGridForProjection(projection);
}
return (
/** @type {!module:ol/tilegrid/TileGrid} */ (this.tileGridForProjection[projKey])
);
}
};
/**
* @inheritDoc
*/
TileImage.prototype.getTileCacheForProjection = function(projection) {
if (!ENABLE_RASTER_REPROJECTION) {
return UrlTile.prototype.getTileCacheForProjection.call(this, projection);
}
const thisProj = this.getProjection(); if (!thisProj || equivalent(thisProj, projection)) {
return this.tileCache;
} else {
const projKey = getUid(projection).toString();
if (!(projKey in this.tileCacheForProjection)) {
this.tileCacheForProjection[projKey] = new TileCache(this.tileCache.highWaterMark);
}
return this.tileCacheForProjection[projKey];
}
};
/**
* @param {number} z Tile coordinate z.
* @param {number} x Tile coordinate x.
* @param {number} y Tile coordinate y.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @param {string} key The key set on the tile.
* @return {!module:ol/Tile} Tile.
* @private
*/
TileImage.prototype.createTile_ = function(z, x, y, pixelRatio, projection, key) {
const tileCoord = [z, x, y];
const urlTileCoord = this.getTileCoordForTileUrlFunction(
tileCoord, projection);
const tileUrl = urlTileCoord ?
this.tileUrlFunction(urlTileCoord, pixelRatio, projection) : undefined;
const tile = new this.tileClass(
tileCoord,
tileUrl !== undefined ? TileState.IDLE : TileState.EMPTY,
tileUrl !== undefined ? tileUrl : '',
this.crossOrigin,
this.tileLoadFunction,
this.tileOptions);
tile.key = key;
listen(tile, EventType.CHANGE,
this.handleTileChange, this);
return tile;
};
/**
* @inheritDoc
*/
TileImage.prototype.getTile = function(z, x, y, pixelRatio, projection) {
const sourceProjection = /** @type {!module:ol/proj/Projection} */ (this.getProjection());
if (!ENABLE_RASTER_REPROJECTION ||
!sourceProjection || !projection || equivalent(sourceProjection, projection)) {
return this.getTileInternal(z, x, y, pixelRatio, sourceProjection || projection);
} else {
const cache = this.getTileCacheForProjection(projection);
const tileCoord = [z, x, y];
let tile;
const tileCoordKey = getKey(tileCoord);
if (cache.containsKey(tileCoordKey)) {
tile = /** @type {!module:ol/Tile} */ (cache.get(tileCoordKey));
}
const key = this.getKey();
if (tile && tile.key == key) {
return tile;
} else {
const sourceTileGrid = this.getTileGridForProjection(sourceProjection);
const targetTileGrid = this.getTileGridForProjection(projection);
const wrappedTileCoord =
this.getTileCoordForTileUrlFunction(tileCoord, projection);
const newTile = new ReprojTile(
sourceProjection, sourceTileGrid,
projection, targetTileGrid,
tileCoord, wrappedTileCoord, this.getTilePixelRatio(pixelRatio),
this.getGutterInternal(),
function(z, x, y, pixelRatio) {
return this.getTileInternal(z, x, y, pixelRatio, sourceProjection);
}.bind(this), this.reprojectionErrorThreshold_,
this.renderReprojectionEdges_);
newTile.key = key;
if (tile) {
newTile.interimTile = tile;
newTile.refreshInterimChain();
cache.replace(tileCoordKey, newTile);
} else {
cache.set(tileCoordKey, newTile);
}
return newTile;
}
}
};
/**
* @param {number} z Tile coordinate z.
* @param {number} x Tile coordinate x.
* @param {number} y Tile coordinate y.
* @param {number} pixelRatio Pixel ratio.
* @param {!module:ol/proj/Projection} projection Projection.
* @return {!module:ol/Tile} Tile.
* @protected
*/
TileImage.prototype.getTileInternal = function(z, x, y, pixelRatio, projection) {
let tile = null;
const tileCoordKey = getKeyZXY(z, x, y);
const key = this.getKey();
if (!this.tileCache.containsKey(tileCoordKey)) {
tile = this.createTile_(z, x, y, pixelRatio, projection, key);
this.tileCache.set(tileCoordKey, tile);
} else {
tile = this.tileCache.get(tileCoordKey);
if (tile.key != key) {
// The source's params changed. If the tile has an interim tile and if we
// can use it then we use it. Otherwise we create a new tile. In both
// cases we attempt to assign an interim tile to the new tile.
const interimTile = tile;
tile = this.createTile_(z, x, y, pixelRatio, projection, key);
//make the new tile the head of the list,
if (interimTile.getState() == TileState.IDLE) {
//the old tile hasn't begun loading yet, and is now outdated, so we can simply discard it
tile.interimTile = interimTile.interimTile;
} else {
tile.interimTile = interimTile;
}
tile.refreshInterimChain();
this.tileCache.replace(tileCoordKey, tile);
}
}
return tile;
};
/**
* Sets whether to render reprojection edges or not (usually for debugging).
* @param {boolean} render Render the edges.
* @api
*/
TileImage.prototype.setRenderReprojectionEdges = function(render) {
if (!ENABLE_RASTER_REPROJECTION ||
this.renderReprojectionEdges_ == render) {
return;
}
this.renderReprojectionEdges_ = render;
for (const id in this.tileCacheForProjection) {
this.tileCacheForProjection[id].clear();
}
this.changed();
};
/**
* Sets the tile grid to use when reprojecting the tiles to the given
* projection instead of the default tile grid for the projection.
*
* This can be useful when the default tile grid cannot be created
* (e.g. projection has no extent defined) or
* for optimization reasons (custom tile size, resolutions, ...).
*
* @param {module:ol/proj~ProjectionLike} projection Projection.
* @param {module:ol/tilegrid/TileGrid} tilegrid Tile grid to use for the projection.
* @api
*/
TileImage.prototype.setTileGridForProjection = function(projection, tilegrid) {
if (ENABLE_RASTER_REPROJECTION) {
const proj = getProjection(projection);
if (proj) {
const projKey = getUid(proj).toString();
if (!(projKey in this.tileGridForProjection)) {
this.tileGridForProjection[projKey] = tilegrid;
}
}
}
};
/**
* @param {module:ol/ImageTile} imageTile Image tile.
* @param {string} src Source.

View File

@@ -53,137 +53,136 @@ import {createXYZ, extentFromProjection} from '../tilegrid.js';
* @param {module:ol/source/TileJSON~Options=} options TileJSON options.
* @api
*/
const TileJSON = function(options) {
class TileJSON {
constructor(options) {
/**
* @type {TileJSON}
* @private
*/
this.tileJSON_ = null;
/**
* @type {TileJSON}
* @private
*/
this.tileJSON_ = null;
TileImage.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
projection: getProjection('EPSG:3857'),
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
state: SourceState.LOADING,
tileLoadFunction: options.tileLoadFunction,
wrapX: options.wrapX !== undefined ? options.wrapX : true,
transition: options.transition
});
TileImage.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
projection: getProjection('EPSG:3857'),
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
state: SourceState.LOADING,
tileLoadFunction: options.tileLoadFunction,
wrapX: options.wrapX !== undefined ? options.wrapX : true,
transition: options.transition
});
if (options.url) {
if (options.jsonp) {
requestJSONP(options.url, this.handleTileJSONResponse.bind(this),
this.handleTileJSONError.bind(this));
if (options.url) {
if (options.jsonp) {
requestJSONP(options.url, this.handleTileJSONResponse.bind(this),
this.handleTileJSONError.bind(this));
} else {
const client = new XMLHttpRequest();
client.addEventListener('load', this.onXHRLoad_.bind(this));
client.addEventListener('error', this.onXHRError_.bind(this));
client.open('GET', options.url);
client.send();
}
} else if (options.tileJSON) {
this.handleTileJSONResponse(options.tileJSON);
} else {
const client = new XMLHttpRequest();
client.addEventListener('load', this.onXHRLoad_.bind(this));
client.addEventListener('error', this.onXHRError_.bind(this));
client.open('GET', options.url);
client.send();
assert(false, 51); // Either `url` or `tileJSON` options must be provided
}
} else if (options.tileJSON) {
this.handleTileJSONResponse(options.tileJSON);
} else {
assert(false, 51); // Either `url` or `tileJSON` options must be provided
}
};
/**
* @private
* @param {Event} event The load event.
*/
onXHRLoad_(event) {
const client = /** @type {XMLHttpRequest} */ (event.target);
// status will be 0 for file:// urls
if (!client.status || client.status >= 200 && client.status < 300) {
let response;
try {
response = /** @type {TileJSON} */(JSON.parse(client.responseText));
} catch (err) {
this.handleTileJSONError();
return;
}
this.handleTileJSONResponse(response);
} else {
this.handleTileJSONError();
}
}
/**
* @private
* @param {Event} event The error event.
*/
onXHRError_(event) {
this.handleTileJSONError();
}
/**
* @return {TileJSON} The tilejson object.
* @api
*/
getTileJSON() {
return this.tileJSON_;
}
/**
* @protected
* @param {TileJSON} tileJSON Tile JSON.
*/
handleTileJSONResponse(tileJSON) {
const epsg4326Projection = getProjection('EPSG:4326');
const sourceProjection = this.getProjection();
let extent;
if (tileJSON.bounds !== undefined) {
const transform = getTransformFromProjections(
epsg4326Projection, sourceProjection);
extent = applyTransform(tileJSON.bounds, transform);
}
const minZoom = tileJSON.minzoom || 0;
const maxZoom = tileJSON.maxzoom || 22;
const tileGrid = createXYZ({
extent: extentFromProjection(sourceProjection),
maxZoom: maxZoom,
minZoom: minZoom
});
this.tileGrid = tileGrid;
this.tileUrlFunction = createFromTemplates(tileJSON.tiles, tileGrid);
if (tileJSON.attribution !== undefined && !this.getAttributions()) {
const attributionExtent = extent !== undefined ?
extent : epsg4326Projection.getExtent();
this.setAttributions(function(frameState) {
if (intersects(attributionExtent, frameState.extent)) {
return [tileJSON.attribution];
}
return null;
});
}
this.tileJSON_ = tileJSON;
this.setState(SourceState.READY);
}
/**
* @protected
*/
handleTileJSONError() {
this.setState(SourceState.ERROR);
}
}
inherits(TileJSON, TileImage);
/**
* @private
* @param {Event} event The load event.
*/
TileJSON.prototype.onXHRLoad_ = function(event) {
const client = /** @type {XMLHttpRequest} */ (event.target);
// status will be 0 for file:// urls
if (!client.status || client.status >= 200 && client.status < 300) {
let response;
try {
response = /** @type {TileJSON} */(JSON.parse(client.responseText));
} catch (err) {
this.handleTileJSONError();
return;
}
this.handleTileJSONResponse(response);
} else {
this.handleTileJSONError();
}
};
/**
* @private
* @param {Event} event The error event.
*/
TileJSON.prototype.onXHRError_ = function(event) {
this.handleTileJSONError();
};
/**
* @return {TileJSON} The tilejson object.
* @api
*/
TileJSON.prototype.getTileJSON = function() {
return this.tileJSON_;
};
/**
* @protected
* @param {TileJSON} tileJSON Tile JSON.
*/
TileJSON.prototype.handleTileJSONResponse = function(tileJSON) {
const epsg4326Projection = getProjection('EPSG:4326');
const sourceProjection = this.getProjection();
let extent;
if (tileJSON.bounds !== undefined) {
const transform = getTransformFromProjections(
epsg4326Projection, sourceProjection);
extent = applyTransform(tileJSON.bounds, transform);
}
const minZoom = tileJSON.minzoom || 0;
const maxZoom = tileJSON.maxzoom || 22;
const tileGrid = createXYZ({
extent: extentFromProjection(sourceProjection),
maxZoom: maxZoom,
minZoom: minZoom
});
this.tileGrid = tileGrid;
this.tileUrlFunction = createFromTemplates(tileJSON.tiles, tileGrid);
if (tileJSON.attribution !== undefined && !this.getAttributions()) {
const attributionExtent = extent !== undefined ?
extent : epsg4326Projection.getExtent();
this.setAttributions(function(frameState) {
if (intersects(attributionExtent, frameState.extent)) {
return [tileJSON.attribution];
}
return null;
});
}
this.tileJSON_ = tileJSON;
this.setState(SourceState.READY);
};
/**
* @protected
*/
TileJSON.prototype.handleTileJSONError = function() {
this.setState(SourceState.ERROR);
};
export default TileJSON;

View File

@@ -80,320 +80,315 @@ import {appendParams} from '../uri.js';
* @param {module:ol/source/TileWMS~Options=} [opt_options] Tile WMS options.
* @api
*/
const TileWMS = function(opt_options) {
class TileWMS {
constructor(opt_options) {
const options = opt_options || {};
const options = opt_options || {};
const params = options.params || {};
const params = options.params || {};
const transparent = 'TRANSPARENT' in params ? params['TRANSPARENT'] : true;
const transparent = 'TRANSPARENT' in params ? params['TRANSPARENT'] : true;
TileImage.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
opaque: !transparent,
projection: options.projection,
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
tileClass: options.tileClass,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction,
url: options.url,
urls: options.urls,
wrapX: options.wrapX !== undefined ? options.wrapX : true,
transition: options.transition
});
TileImage.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
crossOrigin: options.crossOrigin,
opaque: !transparent,
projection: options.projection,
reprojectionErrorThreshold: options.reprojectionErrorThreshold,
tileClass: options.tileClass,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction,
url: options.url,
urls: options.urls,
wrapX: options.wrapX !== undefined ? options.wrapX : true,
transition: options.transition
});
/**
* @private
* @type {number}
*/
this.gutter_ = options.gutter !== undefined ? options.gutter : 0;
/**
* @private
* @type {!Object}
*/
this.params_ = params;
/**
* @private
* @type {boolean}
*/
this.v13_ = true;
/**
* @private
* @type {module:ol/source/WMSServerType|undefined}
*/
this.serverType_ = /** @type {module:ol/source/WMSServerType|undefined} */ (options.serverType);
/**
* @private
* @type {boolean}
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
/**
* @private
* @type {module:ol/extent~Extent}
*/
this.tmpExtent_ = createEmpty();
this.updateV13_();
this.setKey(this.getKeyForParams_());
}
/**
* Return the GetFeatureInfo URL for the passed coordinate, resolution, and
* projection. Return `undefined` if the GetFeatureInfo URL cannot be
* constructed.
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
* @param {number} resolution Resolution.
* @param {module:ol/proj~ProjectionLike} projection Projection.
* @param {!Object} params GetFeatureInfo params. `INFO_FORMAT` at least should
* be provided. If `QUERY_LAYERS` is not provided then the layers specified
* in the `LAYERS` parameter will be used. `VERSION` should not be
* specified here.
* @return {string|undefined} GetFeatureInfo URL.
* @api
*/
getGetFeatureInfoUrl(coordinate, resolution, projection, params) {
const projectionObj = getProjection(projection);
const sourceProjectionObj = this.getProjection();
let tileGrid = this.getTileGrid();
if (!tileGrid) {
tileGrid = this.getTileGridForProjection(projectionObj);
}
const tileCoord = tileGrid.getTileCoordForCoordAndResolution(coordinate, resolution);
if (tileGrid.getResolutions().length <= tileCoord[0]) {
return undefined;
}
let tileResolution = tileGrid.getResolution(tileCoord[0]);
let tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent_);
let tileSize = toSize(tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
const gutter = this.gutter_;
if (gutter !== 0) {
tileSize = bufferSize(tileSize, gutter, this.tmpSize);
tileExtent = buffer(tileExtent, tileResolution * gutter, tileExtent);
}
if (sourceProjectionObj && sourceProjectionObj !== projectionObj) {
tileResolution = calculateSourceResolution(sourceProjectionObj, projectionObj, coordinate, tileResolution);
tileExtent = transformExtent(tileExtent, projectionObj, sourceProjectionObj);
coordinate = transform(coordinate, projectionObj, sourceProjectionObj);
}
const baseParams = {
'SERVICE': 'WMS',
'VERSION': DEFAULT_WMS_VERSION,
'REQUEST': 'GetFeatureInfo',
'FORMAT': 'image/png',
'TRANSPARENT': true,
'QUERY_LAYERS': this.params_['LAYERS']
};
assign(baseParams, this.params_, params);
const x = Math.floor((coordinate[0] - tileExtent[0]) / tileResolution);
const y = Math.floor((tileExtent[3] - coordinate[1]) / tileResolution);
baseParams[this.v13_ ? 'I' : 'X'] = x;
baseParams[this.v13_ ? 'J' : 'Y'] = y;
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
1, sourceProjectionObj || projectionObj, baseParams);
}
/**
* @inheritDoc
*/
getGutterInternal() {
return this.gutter_;
}
/**
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
getParams() {
return this.params_;
}
/**
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
* @param {module:ol/size~Size} tileSize Tile size.
* @param {module:ol/extent~Extent} tileExtent Tile extent.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @param {Object} params Params.
* @return {string|undefined} Request URL.
* @private
*/
getRequestUrl_(tileCoord, tileSize, tileExtent, pixelRatio, projection, params) {
const urls = this.urls;
if (!urls) {
return undefined;
}
params['WIDTH'] = tileSize[0];
params['HEIGHT'] = tileSize[1];
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
if (!('STYLES' in this.params_)) {
params['STYLES'] = '';
}
if (pixelRatio != 1) {
switch (this.serverType_) {
case WMSServerType.GEOSERVER:
const dpi = (90 * pixelRatio + 0.5) | 0;
if ('FORMAT_OPTIONS' in params) {
params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
} else {
params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
}
break;
case WMSServerType.MAPSERVER:
params['MAP_RESOLUTION'] = 90 * pixelRatio;
break;
case WMSServerType.CARMENTA_SERVER:
case WMSServerType.QGIS:
params['DPI'] = 90 * pixelRatio;
break;
default:
assert(false, 52); // Unknown `serverType` configured
break;
}
}
const axisOrientation = projection.getAxisOrientation();
const bbox = tileExtent;
if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {
let tmp;
tmp = tileExtent[0];
bbox[0] = tileExtent[1];
bbox[1] = tmp;
tmp = tileExtent[2];
bbox[2] = tileExtent[3];
bbox[3] = tmp;
}
params['BBOX'] = bbox.join(',');
let url;
if (urls.length == 1) {
url = urls[0];
} else {
const index = modulo(tileCoordHash(tileCoord), urls.length);
url = urls[index];
}
return appendParams(url, params);
}
/**
* @inheritDoc
*/
getTilePixelRatio(pixelRatio) {
return (!this.hidpi_ || this.serverType_ === undefined) ? 1 :
/** @type {number} */ (pixelRatio);
}
/**
* @private
* @type {number}
* @return {string} The key for the current params.
*/
this.gutter_ = options.gutter !== undefined ? options.gutter : 0;
getKeyForParams_() {
let i = 0;
const res = [];
for (const key in this.params_) {
res[i++] = key + '-' + this.params_[key];
}
return res.join('/');
}
/**
* @inheritDoc
*/
fixedTileUrlFunction(tileCoord, pixelRatio, projection) {
let tileGrid = this.getTileGrid();
if (!tileGrid) {
tileGrid = this.getTileGridForProjection(projection);
}
if (tileGrid.getResolutions().length <= tileCoord[0]) {
return undefined;
}
if (pixelRatio != 1 && (!this.hidpi_ || this.serverType_ === undefined)) {
pixelRatio = 1;
}
const tileResolution = tileGrid.getResolution(tileCoord[0]);
let tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent_);
let tileSize = toSize(
tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
const gutter = this.gutter_;
if (gutter !== 0) {
tileSize = bufferSize(tileSize, gutter, this.tmpSize);
tileExtent = buffer(tileExtent, tileResolution * gutter, tileExtent);
}
if (pixelRatio != 1) {
tileSize = scaleSize(tileSize, pixelRatio, this.tmpSize);
}
const baseParams = {
'SERVICE': 'WMS',
'VERSION': DEFAULT_WMS_VERSION,
'REQUEST': 'GetMap',
'FORMAT': 'image/png',
'TRANSPARENT': true
};
assign(baseParams, this.params_);
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
pixelRatio, projection, baseParams);
}
/**
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
updateParams(params) {
assign(this.params_, params);
this.updateV13_();
this.setKey(this.getKeyForParams_());
}
/**
* @private
* @type {!Object}
*/
this.params_ = params;
/**
* @private
* @type {boolean}
*/
this.v13_ = true;
/**
* @private
* @type {module:ol/source/WMSServerType|undefined}
*/
this.serverType_ = /** @type {module:ol/source/WMSServerType|undefined} */ (options.serverType);
/**
* @private
* @type {boolean}
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
/**
* @private
* @type {module:ol/extent~Extent}
*/
this.tmpExtent_ = createEmpty();
this.updateV13_();
this.setKey(this.getKeyForParams_());
};
updateV13_() {
const version = this.params_['VERSION'] || DEFAULT_WMS_VERSION;
this.v13_ = compareVersions(version, '1.3') >= 0;
}
}
inherits(TileWMS, TileImage);
/**
* Return the GetFeatureInfo URL for the passed coordinate, resolution, and
* projection. Return `undefined` if the GetFeatureInfo URL cannot be
* constructed.
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
* @param {number} resolution Resolution.
* @param {module:ol/proj~ProjectionLike} projection Projection.
* @param {!Object} params GetFeatureInfo params. `INFO_FORMAT` at least should
* be provided. If `QUERY_LAYERS` is not provided then the layers specified
* in the `LAYERS` parameter will be used. `VERSION` should not be
* specified here.
* @return {string|undefined} GetFeatureInfo URL.
* @api
*/
TileWMS.prototype.getGetFeatureInfoUrl = function(coordinate, resolution, projection, params) {
const projectionObj = getProjection(projection);
const sourceProjectionObj = this.getProjection();
let tileGrid = this.getTileGrid();
if (!tileGrid) {
tileGrid = this.getTileGridForProjection(projectionObj);
}
const tileCoord = tileGrid.getTileCoordForCoordAndResolution(coordinate, resolution);
if (tileGrid.getResolutions().length <= tileCoord[0]) {
return undefined;
}
let tileResolution = tileGrid.getResolution(tileCoord[0]);
let tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent_);
let tileSize = toSize(tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
const gutter = this.gutter_;
if (gutter !== 0) {
tileSize = bufferSize(tileSize, gutter, this.tmpSize);
tileExtent = buffer(tileExtent, tileResolution * gutter, tileExtent);
}
if (sourceProjectionObj && sourceProjectionObj !== projectionObj) {
tileResolution = calculateSourceResolution(sourceProjectionObj, projectionObj, coordinate, tileResolution);
tileExtent = transformExtent(tileExtent, projectionObj, sourceProjectionObj);
coordinate = transform(coordinate, projectionObj, sourceProjectionObj);
}
const baseParams = {
'SERVICE': 'WMS',
'VERSION': DEFAULT_WMS_VERSION,
'REQUEST': 'GetFeatureInfo',
'FORMAT': 'image/png',
'TRANSPARENT': true,
'QUERY_LAYERS': this.params_['LAYERS']
};
assign(baseParams, this.params_, params);
const x = Math.floor((coordinate[0] - tileExtent[0]) / tileResolution);
const y = Math.floor((tileExtent[3] - coordinate[1]) / tileResolution);
baseParams[this.v13_ ? 'I' : 'X'] = x;
baseParams[this.v13_ ? 'J' : 'Y'] = y;
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
1, sourceProjectionObj || projectionObj, baseParams);
};
/**
* @inheritDoc
*/
TileWMS.prototype.getGutterInternal = function() {
return this.gutter_;
};
/**
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
TileWMS.prototype.getParams = function() {
return this.params_;
};
/**
* @param {module:ol/tilecoord~TileCoord} tileCoord Tile coordinate.
* @param {module:ol/size~Size} tileSize Tile size.
* @param {module:ol/extent~Extent} tileExtent Tile extent.
* @param {number} pixelRatio Pixel ratio.
* @param {module:ol/proj/Projection} projection Projection.
* @param {Object} params Params.
* @return {string|undefined} Request URL.
* @private
*/
TileWMS.prototype.getRequestUrl_ = function(tileCoord, tileSize, tileExtent,
pixelRatio, projection, params) {
const urls = this.urls;
if (!urls) {
return undefined;
}
params['WIDTH'] = tileSize[0];
params['HEIGHT'] = tileSize[1];
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
if (!('STYLES' in this.params_)) {
params['STYLES'] = '';
}
if (pixelRatio != 1) {
switch (this.serverType_) {
case WMSServerType.GEOSERVER:
const dpi = (90 * pixelRatio + 0.5) | 0;
if ('FORMAT_OPTIONS' in params) {
params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
} else {
params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
}
break;
case WMSServerType.MAPSERVER:
params['MAP_RESOLUTION'] = 90 * pixelRatio;
break;
case WMSServerType.CARMENTA_SERVER:
case WMSServerType.QGIS:
params['DPI'] = 90 * pixelRatio;
break;
default:
assert(false, 52); // Unknown `serverType` configured
break;
}
}
const axisOrientation = projection.getAxisOrientation();
const bbox = tileExtent;
if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {
let tmp;
tmp = tileExtent[0];
bbox[0] = tileExtent[1];
bbox[1] = tmp;
tmp = tileExtent[2];
bbox[2] = tileExtent[3];
bbox[3] = tmp;
}
params['BBOX'] = bbox.join(',');
let url;
if (urls.length == 1) {
url = urls[0];
} else {
const index = modulo(tileCoordHash(tileCoord), urls.length);
url = urls[index];
}
return appendParams(url, params);
};
/**
* @inheritDoc
*/
TileWMS.prototype.getTilePixelRatio = function(pixelRatio) {
return (!this.hidpi_ || this.serverType_ === undefined) ? 1 :
/** @type {number} */ (pixelRatio);
};
/**
* @private
* @return {string} The key for the current params.
*/
TileWMS.prototype.getKeyForParams_ = function() {
let i = 0;
const res = [];
for (const key in this.params_) {
res[i++] = key + '-' + this.params_[key];
}
return res.join('/');
};
/**
* @inheritDoc
*/
TileWMS.prototype.fixedTileUrlFunction = function(tileCoord, pixelRatio, projection) {
let tileGrid = this.getTileGrid();
if (!tileGrid) {
tileGrid = this.getTileGridForProjection(projection);
}
if (tileGrid.getResolutions().length <= tileCoord[0]) {
return undefined;
}
if (pixelRatio != 1 && (!this.hidpi_ || this.serverType_ === undefined)) {
pixelRatio = 1;
}
const tileResolution = tileGrid.getResolution(tileCoord[0]);
let tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent_);
let tileSize = toSize(
tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
const gutter = this.gutter_;
if (gutter !== 0) {
tileSize = bufferSize(tileSize, gutter, this.tmpSize);
tileExtent = buffer(tileExtent, tileResolution * gutter, tileExtent);
}
if (pixelRatio != 1) {
tileSize = scaleSize(tileSize, pixelRatio, this.tmpSize);
}
const baseParams = {
'SERVICE': 'WMS',
'VERSION': DEFAULT_WMS_VERSION,
'REQUEST': 'GetMap',
'FORMAT': 'image/png',
'TRANSPARENT': true
};
assign(baseParams, this.params_);
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
pixelRatio, projection, baseParams);
};
/**
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
TileWMS.prototype.updateParams = function(params) {
assign(this.params_, params);
this.updateV13_();
this.setKey(this.getKeyForParams_());
};
/**
* @private
*/
TileWMS.prototype.updateV13_ = function() {
const version = this.params_['VERSION'] || DEFAULT_WMS_VERSION;
this.v13_ = compareVersions(version, '1.3') >= 0;
};
export default TileWMS;

View File

@@ -37,56 +37,173 @@ import {getKeyZXY} from '../tilecoord.js';
* @extends {module:ol/source/Tile}
* @param {module:ol/source/UrlTile~Options=} options Image tile options.
*/
const UrlTile = function(options) {
class UrlTile {
constructor(options) {
TileSource.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
extent: options.extent,
opaque: options.opaque,
projection: options.projection,
state: options.state,
tileGrid: options.tileGrid,
tilePixelRatio: options.tilePixelRatio,
wrapX: options.wrapX,
transition: options.transition
});
TileSource.call(this, {
attributions: options.attributions,
cacheSize: options.cacheSize,
extent: options.extent,
opaque: options.opaque,
projection: options.projection,
state: options.state,
tileGrid: options.tileGrid,
tilePixelRatio: options.tilePixelRatio,
wrapX: options.wrapX,
transition: options.transition
});
/**
* @protected
* @type {module:ol/Tile~LoadFunction}
*/
this.tileLoadFunction = options.tileLoadFunction;
/**
* @protected
* @type {module:ol/Tile~LoadFunction}
*/
this.tileLoadFunction = options.tileLoadFunction;
/**
* @protected
* @type {module:ol/Tile~UrlFunction}
*/
this.tileUrlFunction = this.fixedTileUrlFunction ?
this.fixedTileUrlFunction.bind(this) : nullTileUrlFunction;
/**
* @protected
* @type {module:ol/Tile~UrlFunction}
*/
this.tileUrlFunction = this.fixedTileUrlFunction ?
this.fixedTileUrlFunction.bind(this) : nullTileUrlFunction;
/**
* @protected
* @type {!Array.<string>|null}
*/
this.urls = null;
/**
* @protected
* @type {!Array.<string>|null}
*/
this.urls = null;
if (options.urls) {
this.setUrls(options.urls);
} else if (options.url) {
this.setUrl(options.url);
}
if (options.tileUrlFunction) {
this.setTileUrlFunction(options.tileUrlFunction);
}
/**
* @private
* @type {!Object.<number, boolean>}
*/
this.tileLoadingKeys_ = {};
if (options.urls) {
this.setUrls(options.urls);
} else if (options.url) {
this.setUrl(options.url);
}
if (options.tileUrlFunction) {
this.setTileUrlFunction(options.tileUrlFunction);
}
/**
* @private
* @type {!Object.<number, boolean>}
* Return the tile load function of the source.
* @return {module:ol/Tile~LoadFunction} TileLoadFunction
* @api
*/
this.tileLoadingKeys_ = {};
getTileLoadFunction() {
return this.tileLoadFunction;
}
};
/**
* Return the tile URL function of the source.
* @return {module:ol/Tile~UrlFunction} TileUrlFunction
* @api
*/
getTileUrlFunction() {
return this.tileUrlFunction;
}
/**
* Return the URLs used for this source.
* When a tileUrlFunction is used instead of url or urls,
* null will be returned.
* @return {!Array.<string>|null} URLs.
* @api
*/
getUrls() {
return this.urls;
}
/**
* Handle tile change events.
* @param {module:ol/events/Event} event Event.
* @protected
*/
handleTileChange(event) {
const tile = /** @type {module:ol/Tile} */ (event.target);
const uid = getUid(tile);
const tileState = tile.getState();
let type;
if (tileState == TileState.LOADING) {
this.tileLoadingKeys_[uid] = true;
type = TileEventType.TILELOADSTART;
} else if (uid in this.tileLoadingKeys_) {
delete this.tileLoadingKeys_[uid];
type = tileState == TileState.ERROR ? TileEventType.TILELOADERROR :
(tileState == TileState.LOADED || tileState == TileState.ABORT) ?
TileEventType.TILELOADEND : undefined;
}
if (type != undefined) {
this.dispatchEvent(new TileSourceEvent(type, tile));
}
}
/**
* Set the tile load function of the source.
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
* @api
*/
setTileLoadFunction(tileLoadFunction) {
this.tileCache.clear();
this.tileLoadFunction = tileLoadFunction;
this.changed();
}
/**
* Set the tile URL function of the source.
* @param {module:ol/Tile~UrlFunction} tileUrlFunction Tile URL function.
* @param {string=} opt_key Optional new tile key for the source.
* @api
*/
setTileUrlFunction(tileUrlFunction, opt_key) {
this.tileUrlFunction = tileUrlFunction;
this.tileCache.pruneExceptNewestZ();
if (typeof opt_key !== 'undefined') {
this.setKey(opt_key);
} else {
this.changed();
}
}
/**
* Set the URL to use for requests.
* @param {string} url URL.
* @api
*/
setUrl(url) {
const urls = this.urls = expandUrl(url);
this.setTileUrlFunction(this.fixedTileUrlFunction ?
this.fixedTileUrlFunction.bind(this) :
createFromTemplates(urls, this.tileGrid), url);
}
/**
* Set the URLs to use for requests.
* @param {Array.<string>} urls URLs.
* @api
*/
setUrls(urls) {
this.urls = urls;
const key = urls.join('\n');
this.setTileUrlFunction(this.fixedTileUrlFunction ?
this.fixedTileUrlFunction.bind(this) :
createFromTemplates(urls, this.tileGrid), key);
}
/**
* @inheritDoc
*/
useTile(z, x, y) {
const tileCoordKey = getKeyZXY(z, x, y);
if (this.tileCache.containsKey(tileCoordKey)) {
this.tileCache.get(tileCoordKey);
}
}
}
inherits(UrlTile, TileSource);
@@ -97,126 +214,4 @@ inherits(UrlTile, TileSource);
*/
UrlTile.prototype.fixedTileUrlFunction;
/**
* Return the tile load function of the source.
* @return {module:ol/Tile~LoadFunction} TileLoadFunction
* @api
*/
UrlTile.prototype.getTileLoadFunction = function() {
return this.tileLoadFunction;
};
/**
* Return the tile URL function of the source.
* @return {module:ol/Tile~UrlFunction} TileUrlFunction
* @api
*/
UrlTile.prototype.getTileUrlFunction = function() {
return this.tileUrlFunction;
};
/**
* Return the URLs used for this source.
* When a tileUrlFunction is used instead of url or urls,
* null will be returned.
* @return {!Array.<string>|null} URLs.
* @api
*/
UrlTile.prototype.getUrls = function() {
return this.urls;
};
/**
* Handle tile change events.
* @param {module:ol/events/Event} event Event.
* @protected
*/
UrlTile.prototype.handleTileChange = function(event) {
const tile = /** @type {module:ol/Tile} */ (event.target);
const uid = getUid(tile);
const tileState = tile.getState();
let type;
if (tileState == TileState.LOADING) {
this.tileLoadingKeys_[uid] = true;
type = TileEventType.TILELOADSTART;
} else if (uid in this.tileLoadingKeys_) {
delete this.tileLoadingKeys_[uid];
type = tileState == TileState.ERROR ? TileEventType.TILELOADERROR :
(tileState == TileState.LOADED || tileState == TileState.ABORT) ?
TileEventType.TILELOADEND : undefined;
}
if (type != undefined) {
this.dispatchEvent(new TileSourceEvent(type, tile));
}
};
/**
* Set the tile load function of the source.
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
* @api
*/
UrlTile.prototype.setTileLoadFunction = function(tileLoadFunction) {
this.tileCache.clear();
this.tileLoadFunction = tileLoadFunction;
this.changed();
};
/**
* Set the tile URL function of the source.
* @param {module:ol/Tile~UrlFunction} tileUrlFunction Tile URL function.
* @param {string=} opt_key Optional new tile key for the source.
* @api
*/
UrlTile.prototype.setTileUrlFunction = function(tileUrlFunction, opt_key) {
this.tileUrlFunction = tileUrlFunction;
this.tileCache.pruneExceptNewestZ();
if (typeof opt_key !== 'undefined') {
this.setKey(opt_key);
} else {
this.changed();
}
};
/**
* Set the URL to use for requests.
* @param {string} url URL.
* @api
*/
UrlTile.prototype.setUrl = function(url) {
const urls = this.urls = expandUrl(url);
this.setTileUrlFunction(this.fixedTileUrlFunction ?
this.fixedTileUrlFunction.bind(this) :
createFromTemplates(urls, this.tileGrid), url);
};
/**
* Set the URLs to use for requests.
* @param {Array.<string>} urls URLs.
* @api
*/
UrlTile.prototype.setUrls = function(urls) {
this.urls = urls;
const key = urls.join('\n');
this.setTileUrlFunction(this.fixedTileUrlFunction ?
this.fixedTileUrlFunction.bind(this) :
createFromTemplates(urls, this.tileGrid), key);
};
/**
* @inheritDoc
*/
UrlTile.prototype.useTile = function(z, x, y) {
const tileCoordKey = getKeyZXY(z, x, y);
if (this.tileCache.containsKey(tileCoordKey)) {
this.tileCache.get(tileCoordKey);
}
};
export default UrlTile;