OpenLayers源码阅读(三):ImageWMS及ImageArcGISRest


前提:需要理解常见的地图服务WMS、WMTS、WFS等,针对本文,主要理解WMS服务及其GetCapabilities、GetMap、GetFeatureInfo操作即可。

说明:本文重点关注ol.source.Image部分

1、我们如何使用(

官网例子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、属性有哪些

这里写图片描述
这里重点关注以下几个属性:

  • serverType:mapserver、geoserver、qgis
  • imageLoadFunction:返回image url
  • params:① Layers 必须;② Styles; ③ Version; ④ Width;⑤ Heigh; t⑥ Bbox ⑦CRS;⑧……(自定义key-value)
  • projection
  • ratio 与size of the map viewport的比率,默认是1.5
  • resolutions
  • url:WMS service URL

官网例子中的url:https://ahocevar.com/geoserver/wms
或者也可以定义imageLoadFunction参数
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(该地址就是标准的WMS的GetMap的操作)

3、阅读源码

3.1 imagewms.js

https://github.com/openlayers/openlayers/blob/v4.6.5/src/ol/source/imagewms.js

第一步 构造函数、定义属性信息

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;

};

第二步 继承 ol.source.Image

(参考Openlayer源码阅读(一):从ol开始

ol.inherits(ol.source.ImageWMS, ol.source.Image);

第三步 定义方法(与属性有关、闭包)

/**
 * 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();
  }
};
......

第四步 定义方法(getRequestUrl_、getGetFeatureInfoUrl )

返回image的url
方法getGetFeatureInfoUrl与getRequestUrl_ 类似,不在赘述

/**
 * @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);
};

过程及结果:
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”

return 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

第五步 定义方法(getImageInternal)

返回image的信息(包括url),这里要阅读ol.source.Image和ol.layer..Image

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
基本与imagewms.js一致,除了在image的url的拼接上做了特殊的处理

//在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、总结

  • imagewms主要包含:一是定义属性,二是返回image对象
  • image的url等于url+params
  • url中的params的拼接采用key-value的方式进行的,因此在对地图服务地址进行加密代理的话,就要有针对性的设置params;arcgis服务代理时,建议以MapServer/ImageServer结尾
例如:/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
})

转载自:https://blog.csdn.net/u013240519/article/details/82687116

You may also like...