Premise: we need to understand the common map services WMS, WMTS, WFS, etc. for this article, we mainly understand WMS services and their GetCapabilities, GetMap, GetFeatureInfo operations.
Note: This article focuses on ol.source.Image
1. How do we use(
Official website example http://openlayers.org/en/v4.6.5/examples/wms-image.html?q=wms)
var layers = [
new ol.layer.Image({
extent: [-13884991, 2870341, -7455066, 6338219],
source: new ol.source.ImageWMS({
url: 'https://ahocevar.com/geoserver/wms',
params: {'LAYERS': 'topp:states'},
ratio: 1,
serverType: 'geoserver'
})
})
];
2. What are the attributes
Here we focus on the following attributes:
- serverType: mapserver,geoserver,qgis
- imageLoadFunction: return image url
- params: ① Layers must; ② Styles; ③ Version; ④ Width; ⑤ height; t ⑥ Bbox ⑦ CRS; ⑧ (custom key value)
- projection
- ratio to size of the map viewport, default is 1.5
- resolutions
- url: WMS service URL
url in the official website example: https://ahocevar.com/geoserver/wms
Or you can define the imageLoadFunction parameter
image url:https://ahocevar.com/geoserver/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&LAYERS=topp%3Astates&CRS=EPSG%3A3857&STYLES=&WIDTH=658&HEIGHT=355&BBOX=-13888944.635145342%2C2867630.7173607955%2C-7451112.364854658%2C6340929.2826392045 (this address is the operation of GetMap of standard WMS)
3. Read the source code
3.1 imagewms.js
https://github.com/openlayers/openlayers/blob/v4.6.5/src/ol/source/imagewms.js
Step 1: constructor, defining attribute information
ol.source.ImageWMS = function(opt_options) {
var options = opt_options || {};
ol.source.Image.call(this, {
attributions: options.attributions,
logo: options.logo,
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 {ol.ImageLoadFunctionType}
*/
this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
options.imageLoadFunction : ol.source.Image.defaultImageLoadFunction;
/**
* @private
* @type {!Object}
*/
this.params_ = options.params || {};
/**
* @private
* @type {boolean}
*/
this.v13_ = true;
this.updateV13_();
/**
* @private
* @type {ol.source.WMSServerType|undefined}
*/
this.serverType_ = /** @type {ol.source.WMSServerType|undefined} */ (options.serverType);
/**
* @private
* @type {boolean}
*/
this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
/**
* @private
* @type {ol.Image}
*/
this.image_ = null;
/**
* @private
* @type {ol.Size}
*/
this.imageSize_ = [0, 0];
/**
* @private
* @type {number}
*/
this.renderedRevision_ = 0;
/**
* @private
* @type {number}
*/
this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
};
Step 2 inherit ol.source.Image
(Reference) Openlayer source reading (1): from ol)
ol.inherits(ol.source.ImageWMS, ol.source.Image);
Step 3: define methods (related to properties, closures)
/**
* Return the URL used for this WMS source.
* @return {string|undefined} URL.
* @api
*/
ol.source.ImageWMS.prototype.getUrl = function() {
return this.url_;
};
/**
* Set the URL to use for requests.
* @param {string|undefined} url URL.
* @api
*/
ol.source.ImageWMS.prototype.setUrl = function(url) {
if (url != this.url_) {
this.url_ = url;
this.image_ = null;
this.changed();
}
};
......
Step 4: define methods (getRequestUrl, getGetFeatureInfoUrl)
Return the url of image
The method getGetFeatureInfoUrl is similar to getRequestUrl, which will not be repeated
/**
* @param {ol.Extent} extent Extent.
* @param {ol.Size} size Size.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @param {Object} params Params.
* @return {string} Request URL.
* @private
*/
ol.source.ImageWMS.prototype.getRequestUrl_ = function(extent, size, pixelRatio, projection, params) {
ol.asserts.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 ol.source.WMSServerType.GEOSERVER:
var dpi = (90 * pixelRatio + 0.5) | 0;
if ('FORMAT_OPTIONS' in params) {
params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
} else {
params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
}
break;
case ol.source.WMSServerType.MAPSERVER:
params['MAP_RESOLUTION'] = 90 * pixelRatio;
break;
case ol.source.WMSServerType.CARMENTA_SERVER:
case ol.source.WMSServerType.QGIS:
params['DPI'] = 90 * pixelRatio;
break;
default:
ol.asserts.assert(false, 8); // Unknown `serverType` configured
break;
}
}
params['WIDTH'] = size[0];
params['HEIGHT'] = size[1];
var axisOrientation = projection.getAxisOrientation();
var 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 ol.uri.appendParams(/** @type {string} */ (this.url_), params);
};
Process and results:
0: "SERVICE=WMS"
1: "VERSION=1.3.0"
2: "REQUEST=GetMap"
3: "FORMAT=image%2Fpng"
4: "TRANSPARENT=true"
5: "LAYERS=topp%3Astates"
6: "CRS=EPSG%3A3857"
7: "STYLES="
8: "WIDTH=658"
9: "HEIGHT=355"
10: "BBOX=-13888944.635145342%2C2867630.7173607955%2C-7451112.364854658%2C6340929.2826392045"
Step 5: define the method (getImageInternal)
Return the information of image (including url). Read ol.source.Image here
ol.source.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;
}
var imageResolution = resolution / pixelRatio;
var center = ol.extent.getCenter(extent);
var viewWidth = Math.ceil(ol.extent.getWidth(extent) / imageResolution);
var viewHeight = Math.ceil(ol.extent.getHeight(extent) / imageResolution);
var viewExtent = ol.extent.getForViewAndSize(center, imageResolution, 0,
[viewWidth, viewHeight]);
var requestWidth = Math.ceil(this.ratio_ * ol.extent.getWidth(extent) / imageResolution);
var requestHeight = Math.ceil(this.ratio_ * ol.extent.getHeight(extent) / imageResolution);
var requestExtent = ol.extent.getForViewAndSize(center, imageResolution, 0,
[requestWidth, requestHeight]);
var image = this.image_;
if (image &&
this.renderedRevision_ == this.getRevision() &&
image.getResolution() == resolution &&
image.getPixelRatio() == pixelRatio &&
ol.extent.containsExtent(image.getExtent(), viewExtent)) {
return image;
}
var params = {
'SERVICE': 'WMS',
'VERSION': ol.DEFAULT_WMS_VERSION,
'REQUEST': 'GetMap',
'FORMAT': 'image/png',
'TRANSPARENT': true
};
ol.obj.assign(params, this.params_);
this.imageSize_[0] = Math.round(ol.extent.getWidth(requestExtent) / imageResolution);
this.imageSize_[1] = Math.round(ol.extent.getHeight(requestExtent) / imageResolution);
var url = this.getRequestUrl_(requestExtent, this.imageSize_, pixelRatio,
projection, params);
this.image_ = new ol.Image(requestExtent, resolution, pixelRatio,
url, this.crossOrigin_, this.imageLoadFunction_);
this.renderedRevision_ = this.getRevision();
ol.events.listen(this.image_, ol.events.EventType.CHANGE,
this.handleImageChange, this);
return this.image_;
};
3.2 imagearcgisrest.js
[2] https://github.com/openlayers/openlayers/blob/v4.6.5/src/ol/source/imagearcgisrest.js
It is basically the same as imagewms.js, except for the special processing of image url splicing
//In getImageInternal
var params = {
'F': 'image',
'FORMAT': 'PNG32',
'TRANSPARENT': true
};
ol.obj.assign(params, this.params_);
/**
* @param {ol.Extent} extent Extent.
* @param {ol.Size} size Size.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @param {Object} params Params.
* @return {string} Request URL.
* @private
*/
ol.source.ImageArcGISRest.prototype.getRequestUrl_ = function(extent, size, pixelRatio, projection, params) {
// ArcGIS Server only wants the numeric portion of the projection ID.
var 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);
var url = this.url_;
var modifiedUrl = url
.replace(/MapServer\/?$/, 'MapServer/export')
.replace(/ImageServer\/?$/, 'ImageServer/exportImage');
if (modifiedUrl == url) {
ol.asserts.assert(false, 50); // `options.featureTypes` should be an Array
}
return ol.uri.appendParams(modifiedUrl, params);
};
4, summary
- imagewms mainly includes: defining attributes and returning image objects
- image url equals url+params
- The splicing of params in url adopts the key value method, so when encrypting the map service address, it is necessary to set params specifically; when arcgis service agent, it is recommended to end with MapServer/ImageServer
For example:/WMSUrl:https://ahocevar.com/geoserver/wms?token=111222
var url = WMSUrl.substr(0,WMSUrl.indexOf("?"));
source : new ol.source.ImageWMS({
ratio: 1,
params: {
layers:"topp:states" //"show:"+layerIndex
token:"111222"
},
url: url
})