Openlayers实现测量功能

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

由于公司项目需要使用到openlayers,就开始学习了openlayers,其中有一个需求需要用到测量功能,就参考《WebGisOpenlayers全面解析》写了一个小demo,话不多说,直接上代码:

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title></title>

<link rel="stylesheet" href="./ol.css" type="text/css">

<script src="./ol.js" type="text/javascript"></script>

<link href="https://cdn.bootcss.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet">

<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>

<script src="https://cdn.bootcss.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>

<style type="text/css">

#map {

width: 100%;

height: 100%;

position: absolute;

}

#menu {

float: left;

position: absolute;

bottom: 50px;

right: 30px;

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: #ffffff;

color: black;

border: 1px solid white;

}

.tooltip-measure:before,

.tooltip-static:before {

border-top: 6px solid rgba(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: #ffffff;

}

#scalebar {

float: left;

margin-bottom: 10px;

}

</style>

</head>

<body>

<div id="map">

<div id="menu">

<label>测量类型选择</label>

<select id="type">

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

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

</select>

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

</div>

</div>

<div id="scalebar"></div>

<script type="text/javascript">

$(function () {

//格式

var format = 'image/png';

var bounds = [73.441277, 18.159829,

135.08693, 53.561771];//范围

//中国各省底图(面)

var ImageMap = new ol.layer.Tile({

source: new ol.source.TileWMS({

ratio: 1,

//自己的服务url

url: 'http://localhost:8080/geoserver/China_Test/wms',

//设置服务参数

params: {

'FORMAT': format,

'VERSION': '1.1.0',

STYLES: '',

//图层信息

LAYERS: 'China_Test:C_Test',

}

})

});

//设置地图投影

var projection = new ol.proj.Projection({

code: 'EPSG:4326',//投影编码

units: 'degrees',

axisOrientation: 'neu'

});

//设置地图 实例化一个地图

var map = new ol.Map({

//地图中的比例尺等控制要素

controls: ol.control.defaults({

attribution: false

}).extend([

new ol.control.FullScreen(),//全屏显示

]),

//设置显示的容器

target: 'map',

//设置图层

layers: [

//添加图层

ImageMap

],

//设置视图

view: new ol.View({

//设置投影

projection: projection,

center: [102.73333, 25.05], //初始在某一点

minZoom: 3,

zoom: 5, //缩放级别

}),

});

//定义矢量数据源

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: '#e21e0a',

width: 2

}),

image: new ol.style.Circle({

radius: 5,

fill: new ol.style.Fill({

color: '#ffcc33'

})

})

})

});

//将矢量图层添加到地图中

map.addLayer(vector);

//添加比例尺控件

var scaleLineControl = new ol.control.ScaleLine({

units: 'metric',

target: 'scalebar',

className: 'ol-scale-line'

});

map.addControl(scaleLineControl);

//实例化鼠标位置控件

var mousePositionControl = new ol.control.MousePosition({

coodrdinateFormat: ol.coordinate.createStringXY(4),//坐标格式

//地图投影坐标系

projection: new ol.proj.Projection({

code: 'EPSG:4326',//投影编码

units: 'degrees',

axisOrientation: 'neu'

}),

//className:'tip',

target: document.getElementById('tip'),//显示鼠标位置信息的目标容器

undefinedHTML: '&nbsp;'//未定义坐标标记

});

//添加鼠标位置控件

map.addControl(mousePositionControl);

//实例化鹰眼控件

var overviewMapControl = new ol.control.OverviewMap({

//在鹰眼中相同坐标系下不通数据源的图层

layers: [

new ol.layer.Tile({

source: new ol.source.OSM({

'url': 'http://{a-c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png'

})

})

],

collapseLabel: '\u00BB',

lable: '\u00AB',

collapsed: false,

});

//添加鹰眼

map.addControl(overviewMapControl);

//创建一个WGS84球体对象

var wgs84Sphere = new ol.Sphere(6378137);

//创建一个当前要绘制的对象

var sketch = new ol.Feature();

//创建一个帮助提示框对象

var helpTooltipElement;

//创建一个帮助提示信息对象

var helpTooltip;

//创建一个测量提示框对象

var measureTooltipElement;

//创建一个测量提示信息对象

var measureTooltip;

//继续绘制多边形的提示信息

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

//继续绘制线段的提示信息

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

//鼠标移动触发的函数

var pointerMoveHandler = function (evt) {

//Indicates if the map is currently being dragged.

//Only set for POINTERDRAG and POINTERMOVE events. Default is false.

//如果是平移地图则直接结束

if (evt.dragging) {

return;

}

//帮助提示信息

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');

};

//触发pointermove事件

map.on('pointermove', pointerMoveHandler);

//当鼠标移除地图视图的时为帮助提示要素添加隐藏样式

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

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

});

//获取大地测量复选框

var geodesicCheckbox = document.getElementById('geodesic');

//获取类型

var typeSelect = document.getElementById('type');

//定义一个交互式绘图对象

var draw;

//添加交互式绘图对象的函数

function addInteraction() {

// 获取当前选择的绘制类型

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

//创建一个交互式绘图对象

draw = new ol.interaction.Draw({

//绘制的数据源

source: source,

//绘制类型

type: 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;

//定义一个控制鼠标点击次数的变量

var count = 0;

//绘制开始事件

draw.on('drawstart', function (evt) {

//The feature being drawn.

sketch = evt.feature;

//提示框的坐标

var tooltipCoord = evt.coordinate;

//监听几何要素的change事件

//Increases the revision counter and dispatches a 'change' event.

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

//The event target.

//获取绘制的几何对象

var geom = evt.target;

//定义一个输出对象,用于记录面积和长度

var output;

if (geom instanceof ol.geom.Polygon) {

map.removeEventListener('singleclick');

map.removeEventListener('dblclick');

//输出多边形的面积

output = formatArea(geom);

//获取多变形内部点的坐标

tooltipCoord = geom.getInteriorPoint().getCoordinates();

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

//输出多线段的长度

output = formatLength(geom);

//获取多线段的最后一个点的坐标

tooltipCoord = geom.getLastCoordinate();

}

//设置测量提示框的内标签为最终输出结果

measureTooltipElement.innerHTML = output;

//设置测量提示信息的位置坐标

measureTooltip.setPosition(tooltipCoord);

});

//地图单击事件

map.on('singleclick', function (evt) {

//设置测量提示信息的位置坐标,用来确定鼠标点击后测量提示框的位置

measureTooltip.setPosition(evt.coordinate);

//如果是第一次点击,则设置测量提示框的文本内容为起点

if (count == 0) {

measureTooltipElement.innerHTML = "起点";

}

//根据鼠标点击位置生成一个点

var point = new ol.geom.Point(evt.coordinate);

//将该点要素添加到矢量数据源中

source.addFeature(new ol.Feature(point));

//更改测量提示框的样式,使测量提示框可见

measureTooltipElement.className = 'tooltip tooltip-static';

//创建测量提示框

createMeasureTooltip();

//点击次数增加

count++;

});

//地图双击事件

map.on('dblclick', function (evt) {

var point = new ol.geom.Point(evt.coordinate);

source.addFeature(new ol.Feature(point));

});

}, this);

//绘制结束事件

draw.on('drawend', function (evt) {

count = 0;

//设置测量提示框的样式

measureTooltipElement.className = 'tooltip tooltip-static';

//设置偏移量

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

//清空绘制要素

sketch = null;

//清空测量提示要素

measureTooltipElement = null;

//创建测量提示框

createMeasureTooltip();

//移除事件监听

ol.Observable.unByKey(listener);

//移除地图单击事件

map.removeEventListener('singleclick');

}, this);

}

//创建帮助提示框

function createHelpTooltip() {

//如果已经存在帮助提示框则移除

if (helpTooltipElement) {

helpTooltipElement.parentNode.removeChild(helpTooltipElement);

}

//创建帮助提示要素的div

helpTooltipElement = document.createElement('div');

//设置帮助提示要素的样式

helpTooltipElement.className = 'tooltip hidden';

//创建一个帮助提示的覆盖标注

helpTooltip = new ol.Overlay({

element: helpTooltipElement,

offset: [15, 0],

positioning: 'center-left'

});

//将帮助提示的覆盖标注添加到地图中

map.addOverlay(helpTooltip);

}

//创建测量提示框

function createMeasureTooltip() {

//创建测量提示框的div

measureTooltipElement = document.createElement('div');

measureTooltipElement.setAttribute('id', 'lengthLabel');

//设置测量提示要素的样式

measureTooltipElement.className = 'tooltip tooltip-measure';

//创建一个测量提示的覆盖标注

measureTooltip = new ol.Overlay({

element: measureTooltipElement,

offset: [0, -15],

positioning: 'bottom-center'

});

//将测量提示的覆盖标注添加到地图中

map.addOverlay(measureTooltip);

}

//测量类型发生改变时触发事件

typeSelect.onchange = function () {

//移除之前的绘制对象

map.removeInteraction(draw);

//重新进行绘制

addInteraction();

};

//格式化测量长度

var formatLength = function (line) {

//定义长度变量

var length;

//如果大地测量复选框被勾选,则计算球面距离

if (geodesicCheckbox.checked) {

//获取坐标串

var coordinates = line.getCoordinates();

//初始长度为0

length = 0;

//获取源数据的坐标系

var sourceProj = map.getView().getProjection();

//进行点的坐标转换

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

//第一个点

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

//第二个点

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

//获取转换后的球面距离

//Returns the distance from c1 to c2 using the haversine formula.

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

}

} else {

//计算平面距离

length = Math.round(line.getLength() * 100) / 100;

}

//定义输出变量

var output;

//如果长度大于1000,则使用km单位,否则使用m单位

if (length > 1000) {

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

} else {

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

}

return output;

};

//格式化测量面积

var formatArea = function (polygon) {

//定义面积变量

var area;

//如果大地测量复选框被勾选,则计算球面面积

if (geodesicCheckbox.checked) {

//获取初始坐标系

var sourceProj = map.getView().getProjection();

var geom = polygon.clone().transform(sourceProj, 'EPSG:4326');

//获取多边形的坐标系

var coordinates = geom.getLinearRing(0).getCoordinates();

//获取球面面积

area = Math.abs(wgs84Sphere.geodesicArea(coordinates));

} else {

//获取平面面积

area = polygon.getArea();

}

//定义输出变量

var output;

//当面积大于10000时,转换为平方千米,否则为平方米

if (area > 10000) {

output = (Math.round(area / 1000000 * 100) / 100) + ' ' + 'km<sup>2</sup>';

} else {

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

}

return output;

};

//添加交互绘图对象

addInteraction();

});

</script>

</body>

</html>

效果图:

PS:这里调用的图层是使用geoserver发布的一个组合图层,可以自行定义。

源代码地址:测量实例

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

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

回到顶部