天天看點

OpenLayers 3 之 添加地圖網格前言示例使用實作總結

前言

在地圖上渲染一層類似于經緯線的網格層,更有利于準确的确定區域,在WGS84坐标系下,以度,分,秒為機關,稱之為“經緯網”,其網格是以經緯線來劃分的。在OpenLayers3中,渲染網格的類是“ol.Graticule”。本文中,我結合執行個體,講解“ol.Graticule”的用法和具體實作。

示例

初始化一個網格層,然後将其關聯的map對象設定為map(預先定義好的),網格層便會在關聯的地圖上渲染。初始化網格層可傳的參數和方法下面會說明,例子如下(完整的例子可以到我的GitHub檢視):

var graticuleLayer = new ol.Graticule({
            // map: map,
            strokeStyle: new ol.style.Stroke({
                color: 'rgba(12, 12, 12, 0.8)',
                width: 0.6
            }),
            targetSize: 100
        });
        graticuleLayer.setMap(map);
           

執行結果如下圖:

OpenLayers 3 之 添加地圖網格前言示例使用實作總結

使用

參數

初始化“ol.Gracule”時可調節的參數有四個(map,maxLines,strokeStyle和targetSize),如下:

  • map 參數指定了網格層關聯的地圖對象,也可以不設定該參數,使用其setMap()函數;
  • maxLines 指定以地圖中心為參考,左右經線和上下緯線的最大數量,預設值是 100,這表示将繪制200條經線和緯線。需要注意渲染速度會随着maxLines的變大而下降;
  • strokeStyle 指定線的樣式,值是一個“ol.style.Stroke”對象,如果沒有指定該參數,其預設樣式是rgba(0,0,0,0.2);
  • targetSize 指定每個網格覆寫的區域的大小,機關是像素,預設是100,也就是 10 像素 × 10 像素。

API

“ol.Gracule”對外開放的API也有四個,如下:

  • getMap,取得與網格相關聯的地圖對象;
  • setMap,設定與網格相關聯的地圖對象,網格将在關聯的地圖之上渲染;
  • getMeridians,取得所有經線組成的數組,每條繪制的經線都是“ol.geom.LineString”對象;
  • getParallels,取得所有緯線組成的數組,每條繪制的維線也都是“ol.geom.LineString”對象。

實作

提供的可配置參數和API都比較有限,能做的事情也比較有限,接下來我們看看其實作原理,友善我們對其進行定制改寫。 要了解一個類的具體實作,我們首先要分析其結構,其公私有變量和成員函數,歸納其内部互相調用關系,理清脈絡。“ol.Graticule”的脈絡如下:

OpenLayers 3 之 添加地圖網格前言示例使用實作總結

OL3中的類構造都使用構造函數模式和原型模式,在構造函數中,除了指派一些參數外,最後調用了“setMap”,setMap會對地圖對象的“POSTCOMPOSE”事件綁定“handlePostCompose_”監聽函數,“handlePostCompose_”做了所有初始化并渲染網格的工作。其中,“createGraticule_”做渲染工作,“addMeridian”和“addParallel”做實際的渲染經線和緯線的工作。

setMap

setMap定義如下:

<span style="font-family:Times New Roman;">/**
 * Set the map for this graticule.  The graticule will be rendered on the
 * provided map.
 * @param {ol.Map} map Map.
 * @api
 */
ol.Graticule.prototype.setMap = function(map) {
  if (this.map_) {
    this.map_.un(ol.render.EventType.POSTCOMPOSE,
        this.handlePostCompose_, this);
    this.map_.render();
  }
  if (map) {
    map.on(ol.render.EventType.POSTCOMPOSE,
        this.handlePostCompose_, this);
    map.render();
  }
  this.map_ = map;
};</span>
           

setMap首先判斷初始化時是否指定了“map_”參數,如果指定了,首先解除綁定地圖對象“POSTCOMPOSE”事件的監聽函數“handlePostCompose_”,如果指定新的地圖對象,則對新指定的 map 對象,綁定`POSTCOMPOSE`事件監聽函數“handlePostCompose_”,并調用 map 對象的 render 方法,最後将地圖對象指派給“this.map_”。從以上的類脈絡圖看,“handlePostCompose_”功能是初始化網格并渲染在地圖上,并随着地圖縮放等操作觸發的“POSTCOMPOSE”事件,根據實際情況重新渲染。

addMeridian_&addParallel_

實際的渲染工作是由“addMeridian_”和“addParallel_”完成的,我們選擇一個來進行說明,“addMeridian_”将從“getMeridian_”獲得的經線添加到“this.meridians_”數組,“addMeridian_”函數添加前會判斷經線是否在地圖視口内,如果是才會添加,“handlePostCompose_”将“this.meridians_”數組中的經線對象(lineString)渲染到地圖之上:vectorContext.drawLineString(line, null),“getMeridian”實作如下:

/**
 * @param {number} lon Longitude.
 * @param {number} minLat Minimal latitude.
 * @param {number} maxLat Maximal latitude.
 * @param {number} squaredTolerance Squared tolerance.
 * @return {ol.geom.LineString} The meridian line string.
 * @param {number} index Index.
 * @private
 */
ol.Graticule.prototype.getMeridian_ = function(lon, minLat, maxLat,
                                               squaredTolerance, index) {
  goog.asserts.assert(lon >= this.minLon_,
      'lon should be larger than or equal to this.minLon_');
  goog.asserts.assert(lon <= this.maxLon_,
      'lon should be smaller than or equal to this.maxLon_');
  var flatCoordinates = ol.geom.flat.geodesic.meridian(lon,
      minLat, maxLat, this.projection_, squaredTolerance);
  goog.asserts.assert(flatCoordinates.length > 0,
      'flatCoordinates cannot be empty');
  var lineString = this.meridians_[index] !== undefined ?
      this.meridians_[index] : new ol.geom.LineString(null);
  lineString.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates);
  return lineString;
};
           

ol.geom.flatgeodesic.meridian方法傳回經線的坐标集合, lineString.setFlatCoordinates方法将lineString坐标設定為flatCoordinates,這樣就完成了一條經線的初始化。

總結

本文總結了“ol.Graticule”的用法和具體實作,openlayers3中的網格支援目前還不是很完善,如果需要更多的功能,要自己去擴充和實作。

文中的執行個體可以到我的GitHub下載下傳, 好的,就寫到這裡,有什麼問題,可以在文章下面留言或者給我發郵件。

繼續閱讀