Openlayers實現(xiàn)測量功能
本文實例為大家分享了Openlayers實現(xiàn)測量的具體代碼,供大家參考,具體內(nèi)容如下
由于公司項目需要使用到openlayers,就開始學(xué)習了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 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,
//自己的服務(wù)url
url: 'http://localhost:8080/geoserver/China_Test/wms',
//設(shè)置服務(wù)參數(shù)
params: {
'FORMAT': format,
'VERSION': '1.1.0',
STYLES: '',
//圖層信息
LAYERS: 'China_Test:C_Test',
}
})
});
//設(shè)置地圖投影
var projection = new ol.proj.Projection({
code: 'EPSG:4326',//投影編碼
units: 'degrees',
axisOrientation: 'neu'
});
//設(shè)置地圖 實例化一個地圖
var map = new ol.Map({
//地圖中的比例尺等控制要素
controls: ol.control.defaults({
attribution: false
}).extend([
new ol.control.FullScreen(),//全屏顯示
]),
//設(shè)置顯示的容器
target: 'map',
//設(shè)置圖層
layers: [
//添加圖層
ImageMap
],
//設(shè)置視圖
view: new ol.View({
//設(shè)置投影
projection: projection,
center: [102.73333, 25.05], //初始在某一點
minZoom: 3,
zoom: 5, //縮放級別
}),
});
//定義矢量數(shù)據(jù)源
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: ' '//未定義坐標標記
});
//添加鼠標位置控件
map.addControl(mousePositionControl);
//實例化鷹眼控件
var overviewMapControl = new ol.control.OverviewMap({
//在鷹眼中相同坐標系下不通數(shù)據(jù)源的圖層
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);
//創(chuàng)建一個WGS84球體對象
var wgs84Sphere = new ol.Sphere(6378137);
//創(chuàng)建一個當前要繪制的對象
var sketch = new ol.Feature();
//創(chuàng)建一個幫助提示框?qū)ο?
var helpTooltipElement;
//創(chuàng)建一個幫助提示信息對象
var helpTooltip;
//創(chuàng)建一個測量提示框?qū)ο?
var measureTooltipElement;
//創(chuàng)建一個測量提示信息對象
var measureTooltip;
//繼續(xù)繪制多邊形的提示信息
var continuePolygonMsg = '單擊以繼續(xù)繪制多邊形';
//繼續(xù)繪制線段的提示信息
var continueLineMsg = '單擊以繼續(xù)繪制直線';
//鼠標移動觸發(fā)的函數(shù)
var pointerMoveHandler = function (evt) {
//Indicates if the map is currently being dragged.
//Only set for POINTERDRAG and POINTERMOVE events. Default is false.
//如果是平移地圖則直接結(jié)束
if (evt.dragging) {
return;
}
//幫助提示信息
var helpMsg = '單擊開始';
if (sketch) {
//獲取繪圖對象的幾何要素
var geom = sketch.getGeometry();
//如果當前繪制的幾何要素是多線段,則將繪制提示信息設(shè)置為多線段繪制提示信息
if (geom instanceof ol.geom.Polygon) {
helpMsg = continuePolygonMsg;
} else if (geom instanceof ol.geom.LineString) {
helpMsg = continueLineMsg;
}
}
//設(shè)置幫助提示要素的內(nèi)標簽為幫助提示信息
helpTooltipElement.innerHTML = helpMsg;
//設(shè)置幫助提示信息的位置
helpTooltip.setPosition(evt.coordinate);
//移除幫助提示要素的隱藏樣式
$(helpTooltipElement).removeClass('hidden');
};
//觸發(fā)pointermove事件
map.on('pointermove', pointerMoveHandler);
//當鼠標移除地圖視圖的時為幫助提示要素添加隱藏樣式
$(map.getViewport()).on('mouseout', function () {
$(helpTooltipElement).addClass('hidden');
});
//獲取大地測量復(fù)選框
var geodesicCheckbox = document.getElementById('geodesic');
//獲取類型
var typeSelect = document.getElementById('type');
//定義一個交互式繪圖對象
var draw;
//添加交互式繪圖對象的函數(shù)
function addInteraction() {
// 獲取當前選擇的繪制類型
var type = typeSelect.value == 'area' ? 'Polygon' : 'LineString';
//創(chuàng)建一個交互式繪圖對象
draw = new ol.interaction.Draw({
//繪制的數(shù)據(jù)源
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);
//創(chuàng)建測量提示框
createMeasureTooltip();
//創(chuàng)建幫助提示框
createHelpTooltip();
//定義一個事件監(jiān)聽
var listener;
//定義一個控制鼠標點擊次數(shù)的變量
var count = 0;
//繪制開始事件
draw.on('drawstart', function (evt) {
//The feature being drawn.
sketch = evt.feature;
//提示框的坐標
var tooltipCoord = evt.coordinate;
//監(jiān)聽幾何要素的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);
//獲取多變形內(nèi)部點的坐標
tooltipCoord = geom.getInteriorPoint().getCoordinates();
} else if (geom instanceof ol.geom.LineString) {
//輸出多線段的長度
output = formatLength(geom);
//獲取多線段的最后一個點的坐標
tooltipCoord = geom.getLastCoordinate();
}
//設(shè)置測量提示框的內(nèi)標簽為最終輸出結(jié)果
measureTooltipElement.innerHTML = output;
//設(shè)置測量提示信息的位置坐標
measureTooltip.setPosition(tooltipCoord);
});
//地圖單擊事件
map.on('singleclick', function (evt) {
//設(shè)置測量提示信息的位置坐標,用來確定鼠標點擊后測量提示框的位置
measureTooltip.setPosition(evt.coordinate);
//如果是第一次點擊,則設(shè)置測量提示框的文本內(nèi)容為起點
if (count == 0) {
measureTooltipElement.innerHTML = "起點";
}
//根據(jù)鼠標點擊位置生成一個點
var point = new ol.geom.Point(evt.coordinate);
//將該點要素添加到矢量數(shù)據(jù)源中
source.addFeature(new ol.Feature(point));
//更改測量提示框的樣式,使測量提示框可見
measureTooltipElement.className = 'tooltip tooltip-static';
//創(chuàng)建測量提示框
createMeasureTooltip();
//點擊次數(shù)增加
count++;
});
//地圖雙擊事件
map.on('dblclick', function (evt) {
var point = new ol.geom.Point(evt.coordinate);
source.addFeature(new ol.Feature(point));
});
}, this);
//繪制結(jié)束事件
draw.on('drawend', function (evt) {
count = 0;
//設(shè)置測量提示框的樣式
measureTooltipElement.className = 'tooltip tooltip-static';
//設(shè)置偏移量
measureTooltip.setOffset([0, -7]);
//清空繪制要素
sketch = null;
//清空測量提示要素
measureTooltipElement = null;
//創(chuàng)建測量提示框
createMeasureTooltip();
//移除事件監(jiān)聽
ol.Observable.unByKey(listener);
//移除地圖單擊事件
map.removeEventListener('singleclick');
}, this);
}
//創(chuàng)建幫助提示框
function createHelpTooltip() {
//如果已經(jīng)存在幫助提示框則移除
if (helpTooltipElement) {
helpTooltipElement.parentNode.removeChild(helpTooltipElement);
}
//創(chuàng)建幫助提示要素的div
helpTooltipElement = document.createElement('div');
//設(shè)置幫助提示要素的樣式
helpTooltipElement.className = 'tooltip hidden';
//創(chuàng)建一個幫助提示的覆蓋標注
helpTooltip = new ol.Overlay({
element: helpTooltipElement,
offset: [15, 0],
positioning: 'center-left'
});
//將幫助提示的覆蓋標注添加到地圖中
map.addOverlay(helpTooltip);
}
//創(chuàng)建測量提示框
function createMeasureTooltip() {
//創(chuàng)建測量提示框的div
measureTooltipElement = document.createElement('div');
measureTooltipElement.setAttribute('id', 'lengthLabel');
//設(shè)置測量提示要素的樣式
measureTooltipElement.className = 'tooltip tooltip-measure';
//創(chuàng)建一個測量提示的覆蓋標注
measureTooltip = new ol.Overlay({
element: measureTooltipElement,
offset: [0, -15],
positioning: 'bottom-center'
});
//將測量提示的覆蓋標注添加到地圖中
map.addOverlay(measureTooltip);
}
//測量類型發(fā)生改變時觸發(fā)事件
typeSelect.onchange = function () {
//移除之前的繪制對象
map.removeInteraction(draw);
//重新進行繪制
addInteraction();
};
//格式化測量長度
var formatLength = function (line) {
//定義長度變量
var length;
//如果大地測量復(fù)選框被勾選,則計算球面距離
if (geodesicCheckbox.checked) {
//獲取坐標串
var coordinates = line.getCoordinates();
//初始長度為0
length = 0;
//獲取源數(shù)據(jù)的坐標系
var sourceProj = map.getView().getProjection();
//進行點的坐標轉(zhuǎn)換
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');
//獲取轉(zhuǎn)換后的球面距離
//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;
//如果大地測量復(fù)選框被勾選,則計算球面面積
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時,轉(zhuǎn)換為平方千米,否則為平方米
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:這里調(diào)用的圖層是使用geoserver發(fā)布的一個組合圖層,可以自行定義。
源代碼地址:測量實例
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
javascript實現(xiàn)前端成語點擊驗證優(yōu)化
這篇文章主要介紹了javascript實現(xiàn)前端成語點擊驗證優(yōu)化,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-06-06
微信小程序自定義可滑動頂部TabBar選項卡實現(xiàn)頁面切換功能示例
這篇文章主要介紹了微信小程序自定義可滑動頂部TabBar選項卡實現(xiàn)頁面切換功能,結(jié)合實例形式分析了微信小程序自定義頂部TabBar選項卡頁面切換功能的相關(guān)布局、樣式及功能實現(xiàn)技巧,需要的朋友可以參考下2019-05-05
深入理解事件冒泡(Bubble)和事件捕捉(capture)
下面小編就為大家?guī)硪黄钊肜斫馐录芭?Bubble)和事件捕捉(capture)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-05-05
用JavaScrpt實現(xiàn)文件夾簡單輕松加密的實現(xiàn)方法圖文
電腦里經(jīng)常會存儲著重要文件,這些文件需要進行加密,有許多方法來實現(xiàn)。但如果想對一個文件夾里的所有文件都進行加密,數(shù)量少還可以,要是數(shù)量多豈不是得把人累死?2008-09-09
javascript typeof的用法與typeof運算符介紹[詳細]
下面是對于typeof運算符的詳細介紹跟typeof的一些用法,分析,學(xué)習typeof的朋友,看完了,這篇應(yīng)該能有所收獲。2008-10-10

