/ Openlayers 4

ScaleLine - Openlayers 4 Tutorial

以下内容介绍了在静态图片地图里设置比例尺的方法和相关代码分析

  1. 首先说明 ol.control.ScaleLine 模块使用方式:
var scaleLineControl = new ScaleLineControl({
    //说明比例尺div的className
    className: 'ol-scale-line';
    //说明比例尺的最小长度,默认值64
    minWidth: 64,
    //说明view变化时需要call的回调函数,通常不用设置
    // render: ,
    //说明放置比例尺的HTML元素
    target: 'scalebar',
    //说明比例尺显示的单位
    units: 'metric'      
});
map.addControl(scaleLineControl);
  1. 比例尺实现原理分析:
    以上面的静态图片地图为例,投影系如下:
var projection = new Projection({
    code: 'pixel',
    units: 'pixels',
    extent: [0,0,1000,1000],
    // metersPerUnit: 0.1
});

在 ol.control.SacleLine 的源码中,我们可以得到其大概的实现过程,这里说明一下其中的主要代码:

#158 ol.control.ScaleLine.prototype.updateElement_

当view变化时最终使用这个方法更新比例尺

  var center = viewState.center;
  var projection = viewState.projection;
  var units = this.getUnits();
  var pointResolutionUnits = units == ol.control.ScaleLineUnits.DEGREES ?
    ol.proj.Units.DEGREES :
    ol.proj.Units.METERS;
  var pointResolution =
      ol.proj.getPointResolution(projection, viewState.resolution, center, pointResolutionUnits);

在上面几行代码中,先得到view下的各个参数,通过函数 getPointResolution 用来获取view中心点分辨率

点分辨率(pointResolution):代表了view界面上的一点对应实际地理位置的长度

getPointResolution 定义如下, 源码位置

#71 ol.proj.getPointResolution(projection, resolution, point, opt_units)

getPointResolution 函数获取projection里的units判断是否为degrees,如果是的话pointResolution就等于参数里的resolution,否则

      // Estimate point resolution by transforming the center pixel to EPSG:4326,
      // measuring its width and height on the normal sphere, and taking the
      // average of the width and height.

也就是通过传入的projection与EPSG:4326建立起转换关系,返回一个转换函数toEPSG4326, 把projection下的中心点通过toEPSG4326函数转换成4326投影系下的坐标,然后balabala,后面的计算和我们这里使用的地图没关系,也就是说openlayers会自动转换我们使用的投影系,但是前提是这个投影系必须是公认的,有自己的 The SRS identifier code,但我们这里使用的投影系是自定义的,openlayers 不能识别,所以我们需要换个方法,在代码的74行:

  var getter = projection.getPointResolutionFunc();
  if (getter) {
    pointResolution = getter(resolution, point);
  }

可以看到,openlayers 允许我们自己提供getPointResolution函数,从这里入手,于是在我们的projection下补充以下代码:

      projection.setGetPointResolution(function(resolution, point){
        var metersPerUnit = 0.0082
        var pointResolution = 1 * resolution * metersPerUnit
        return pointResolution;
});

其中resolution是地图分辨率,metersPerUnit是单位图片上的点对应的实际距离。
在得到点分辨率以后,接下来定义比例尺显示的长度和对应的单位后缀,并且更新比例尺UI。

总结:

静态图片的地图使用场景不多,网上大多数资料为地理地图的应用,以上是我在做室内地图时关于比例尺的一部分技术说明,如有不准确的地方欢迎指正。