OpenLayers3实现测量功能

本文实例为大家分享了OpenLayers3实现测量功能的具体代码,供大家参考,具体内容如下

1. 前言

测量功能实现面积的测量以及长度的测量。通过鼠标绘制区域以及长度来进行测量。OpenLayers 3 框架没有提供测量控件,但提供了相应的接口,需要需要基于几何对象的相应接口,结合图形绘制功能实现。

2. 实现思路

(1)新建一个网页,引用 openlayers 3 开发库、jQuery 库与 bootstrap 库,并参照前面显示地图的文章,加载 OSM 瓦片图层。

(2)在地图容器中,创建一个测量类型选择控件,进行选择距离测量与面积测量。

(3)编写代码实现测量功能。

3. 实现代码

html主要代码

<div id="map">

<div id="menu">

<label>测量类型:</label>

<select id="type">

<option value="length">长度</option>

<option value="area">面积</option>

</select>

<label class="checkbox"><input type="checkbox" id="geodesic">使用大地测量</label>

</div>

</div>

测量类型控件的样式设置:

#menu {

float: left;

position: absolute;

bottom: 10px;

left: 10px;

z-index: 2000;

}

.checkbox {

left: 20px;

}

/* 提示框的样式信息 */

.tooltip {

position: relative;

background: rgba(0, 0, 0, 0.5);

border-radius: 4px;

color: white;

padding: 4px 8px;

opacity: 0.7;

white-space: nowrap;

}

.tooltip-measure {

opacity: 1;

font-weight: bold;

}

.tooltip-static {

background-color: #ffcc33;

color: black;

border: 1px solid white;

}

.tooltip-measure::before,

.tooltip-static::before {

border-top: 6px solid rgb(0, 0, 0, 0.5);

border-right: 6px solid transparent;

border-left: 6px solid transparent;

content: "";

position: absolute;

bottom: -6px;

margin-left: -7px;

left: 50%;

}

.tooltip-static::before {

border-top-color: #ffcc33;

}

代码解析

上面的代码是结合 bootstrap库,使用冒泡提示框形式显示当前的测量结果,上面的样式分别设置了两种提示框的样式。

4. 实现测量功能的核心代码

(1)首先在地图上加载测量功能的绘制层,即矢量图层,就相当于,我们画画,需要纸来进行绘画,这里的矢量图层,相当于我们的纸。代码如下:

//加载测量的绘制矢量层

var source = new ol.source.Vector(); //图层数据源

var vector = new ol.layer.Vector({

source: source,

style: new ol.style.Style({ //图层样式

fill: new ol.style.Fill({

color: 'rgba(255, 255, 255, 0.2)' //填充颜色

}),

stroke: new ol.style.Stroke({

color: '#ffcc33', //边框颜色

width: 2 // 边框宽度

}),

image: new ol.style.Circle({

radius: 7,

fill: new ol.style.Fill({

color: '#ffcc33'

})

})

})

});

map.addLayer(vector);

(2)通过 addInteraction 方法实现测量功能,首先加载交互绘图控件(ol.interaction.Draw),也就是我们前面所说的画画需要的笔,在测量时根据测量类型选择绘制线段或多边形,然后分别为交互绘图控件绑定 drawstart 与 drawend 事件。在绘图开始时实时计算当前当前绘制线的长度或多边形的面积,以提示框形式显示,绘图结束时重新创建一个测量提示框显示测量结果。通过 addInteraction 函数实现绘图测量的代码:

4.1 addInteraction 函数实现绘图测量的代码:

/**

* 切换选择测量类型(长度或面积)

* @param {Event} e Change event.

*/

typeSelect.onchange = function(e) {

map.removeInteraction(draw); //移除绘制图形

addInteraction(); //添加绘图进行测量

};

addInteraction(); //调用加载绘制交互控件的方法,添加绘图进行测量

addInteraction()函数代码:

var geodesicCheckbox = document.getElementById('geodesic'); //测地学方式对象

var typeSelect = document.getElementById('type'); //测量类型对象

var draw; // global so we can remove it later

/**

* 加载交互绘制控件函数

*/

function addInteraction() {

var type = (typeSelect.value == 'area' ? 'Polygon' : 'LineString');

draw = new ol.interaction.Draw({

source: source, //测量绘制层数据源

type: /** @type {ol.geom.GeometryType} */ (type), //几何图形类型

style: new ol.style.Style({ //绘制几何图形的样式

fill: new ol.style.Fill({

color: 'rgba(255, 255, 255, 0.2)'

}),

stroke: new ol.style.Stroke({

color: 'rgba(0, 0, 0, 0.5)',

lineDash: [10, 10],

width: 2

}),

image: new ol.style.Circle({

radius: 5,

stroke: new ol.style.Stroke({

color: 'rgba(0, 0, 0, 0.7)'

}),

fill: new ol.style.Fill({

color: 'rgba(255, 255, 255, 0.2)'

})

})

})

});

map.addInteraction(draw);

createMeasureTooltip(); //创建测量工具提示框

createHelpTooltip(); //创建帮助提示框

var listener;

//绑定交互绘制工具开始绘制的事件

draw.on('drawstart',

function(evt) {

// set sketch

sketch = evt.feature; //绘制的要素

/** @type {ol.Coordinate|undefined} */

var tooltipCoord = evt.coordinate; // 绘制的坐标

//绑定change事件,根据绘制几何类型得到测量长度值或面积值,并将其设置到测量工具提示框中显示

listener = sketch.getGeometry().on('change', function(evt) {

var geom = evt.target; //绘制几何要素

var output;

if (geom instanceof ol.geom.Polygon) {

output = formatArea( /** @type {ol.geom.Polygon} */ (geom)); //面积值

tooltipCoord = geom.getInteriorPoint().getCoordinates(); //坐标

} else if (geom instanceof ol.geom.LineString) {

output = formatLength( /** @type {ol.geom.LineString} */ (geom)); //长度值

tooltipCoord = geom.getLastCoordinate(); //坐标

}

measureTooltipElement.innerHTML = output; //将测量值设置到测量工具提示框中显示

measureTooltip.setPosition(tooltipCoord); //设置测量工具提示框的显示位置

});

}, this);

//绑定交互绘制工具结束绘制的事件

draw.on('drawend',

function(evt) {

measureTooltipElement.className = 'tooltip tooltip-static'; //设置测量提示框的样式

measureTooltip.setOffset([0, -7]);

// unset sketch

sketch = null; //置空当前绘制的要素对象

// unset tooltip so that a new one can be created

measureTooltipElement = null; //置空测量工具提示框对象

createMeasureTooltip(); //重新创建一个测试工具提示框显示结果

ol.Observable.unByKey(listener);

}, this);

}

代码解析

首先加载绘图控件(ol.interaction.Draw),也就是我们的笔,在实例化控件时设置当前绘图要素的样式,然后分别调用 createHelpTooltop() 与 createMeasureTooltip() 创建帮助信息提示框和测量工具提示框对象;最后绑定绘图控件对象的 drawstart 与 drawend 事件,实现绘图测量功能。其中,在drawstart 事件处理函数中, 由事件对象得到当前绘制的要素(sketch),通过绘制要素的几何对象绑定 change 事件,根据事件监听的几何对象类型是线或是多边形(ol.geom.Polygon 或 ol.geom.LineString),调用 formatArea() 与 formatLength() 计算输出测量得到的面积值或长度值。

4.2 创建提示框的代码: 

/**

*创建一个新的帮助提示框(tooltip)

*/

function createHelpTooltip() {

if (helpTooltipElement) {

helpTooltipElement.parentNode.removeChild(helpTooltipElement);

}

helpTooltipElement = document.createElement('div');

helpTooltipElement.className = 'tooltip hidden';

helpTooltip = new ol.Overlay({

element: helpTooltipElement,

offset: [15, 0],

positioning: 'center-left'

});

map.addOverlay(helpTooltip);

}

/**

*创建一个新的测量工具提示框(tooltip)

*/

function createMeasureTooltip() {

if (measureTooltipElement) {

measureTooltipElement.parentNode.removeChild(measureTooltipElement);

}

measureTooltipElement = document.createElement('div');

measureTooltipElement.className = 'tooltip tooltip-measure';

measureTooltip = new ol.Overlay({

element: measureTooltipElement,

offset: [0, -15],

positioning: 'bottom-center'

});

map.addOverlay(measureTooltip);

}

代码解析

基于Openlayers 3 的 ol.Overlay 实现创建帮助信息提示框和测量工具提示框,分别通过 createHelpTooltip() 与 createMeasureTooltip() 创建帮助信息提示框和测量工具提示框, ol.Overlay j就是动态创建叠加层对象与其目标容器(div层),并将叠加层对象添加到地图容器中。

4.3 计算长度与面积的代码:

/**

* 测量长度输出

* @param {ol.geom.LineString} line

* @return {string}

*/

var formatLength = function(line) {

var length;

if (geodesicCheckbox.checked) { //若使用测地学方法测量

var coordinates = line.getCoordinates(); //解析线的坐标

length = 0;

var sourceProj = map.getView().getProjection(); //地图数据源投影坐标系

//通过遍历坐标计算两点之前距离,进而得到整条线的长度

for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {

var c1 = ol.proj.transform(coordinates[i], sourceProj, 'EPSG:4326');

var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'EPSG:4326');

length += wgs84Sphere.haversineDistance(c1, c2);

}

} else {

length = Math.round(line.getLength() * 100) / 100; //直接得到线的长度

}

var output;

if (length > 100) {

output = (Math.round(length / 1000 * 100) / 100) + ' ' + 'km'; //换算成KM单位

} else {

output = (Math.round(length * 100) / 100) + ' ' + 'm'; //m为单位

}

return output; //返回线的长度

};

/**

* 测量面积输出

* @param {ol.geom.Polygon} polygon

* @return {string}

*/

var formatArea = function(polygon) {

var area;

if (geodesicCheckbox.checked) { //若使用测地学方法测量

var sourceProj = map.getView().getProjection(); //地图数据源投影坐标系

var geom = /** @type {ol.geom.Polygon} */ (polygon.clone().transform(sourceProj, 'EPSG:4326')); //将多边形要素坐标系投影为EPSG:4326

var coordinates = geom.getLinearRing(0).getCoordinates(); //解析多边形的坐标值

area = Math.abs(wgs84Sphere.geodesicArea(coordinates)); //获取面积

} else {

area = polygon.getArea(); //直接获取多边形的面积

}

var output;

if (area > 10000) {

output = (Math.round(area / 1000000 * 100) / 100) + ' ' + 'km<sup>2</sup>'; //换算成KM单位

} else {

output = (Math.round(area * 100) / 100) + ' ' + 'm<sup>2</sup>'; //m为单位

}

return output; //返回多边形的面积

};

addInteraction(); //调用加载绘制交互控件方法,添加绘图进行测量

代码解析

上面代码通过 formatLength() 与 formatArea() 分别计算输出的长度值以及面积值。计算长度值或者面积值时可以通过两种方法进行计算,一种是使用测地学的方法基于数据的投影坐标系进行计算,另一种是调用几何对象或者多边形对象的方法直接获取值。

(3)开始画画了,分别使用map对象绑定鼠标移动事件(pointermove)和鼠标移除事件(mouseout)。

4.4 添加地图鼠标移动事件的代码:

/**

* 当用户正在绘制多边形时的提示信息文本

* @type {string}

*/

var continuePolygonMsg = '单击继续绘制多边形';

/**

* 当用户正在绘制线时的提示信息文本

* @type {string}

*/

var continueLineMsg = '单击继续绘制线';

/**

* 鼠标移动事件处理函数

* @param {ol.MapBrowserEvent} evt

*/

var pointerMoveHandler = function(evt) {

if (evt.dragging) {

return;

}

/** @type {string} */

var helpMsg = '开始绘制'; //当前默认提示信息

//判断绘制几何类型设置相应的帮助提示信息

if (sketch) {

var geom = (sketch.getGeometry());

if (geom instanceof ol.geom.Polygon) {

helpMsg = continuePolygonMsg; //绘制多边形时提示相应内容

} else if (geom instanceof ol.geom.LineString) {

helpMsg = continueLineMsg; //绘制线时提示相应内容

}

}

helpTooltipElement.innerHTML = helpMsg; //将提示信息设置到对话框中显示

helpTooltip.setPosition(evt.coordinate); //设置帮助提示框的位置

$(helpTooltipElement).removeClass('hidden'); //移除帮助提示框的隐藏样式进行显示

};

map.on('pointermove', pointerMoveHandler); //地图容器绑定鼠标移动事件,动态显示帮助提示框内容

//地图绑定鼠标移出事件,鼠标移出时为帮助提示框设置隐藏样式

$(map.getViewport()).on('mouseout', function() {

$(helpTooltipElement).addClass('hidden');

});

代码解析

鼠标移动事件(pointermove),在回调函数中,根据用户选择测量的类型,在弹窗中显示帮助提示信息,同时为地图容器绑定鼠标移除事件(mouseout),该事件发生后影藏提示框。

5. 实现效果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 OpenLayers3实现测量功能 的全部内容, 来源链接: utcz.com/p/218097.html

回到顶部