首页 > 代码库 > openlayers3 实现测距 面积

openlayers3 实现测距 面积

  1 <!DOCTYPE html> 
  2 <html xmlns="http://www.w3.org/1999/xhtml"> 
  3 <head> 
  4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 
  5 <title></title> 
  6 <link href="http://www.mamicode.com/~/Scripts/OpenLayers-demo/css/ol.css" rel="stylesheet" />
  7 <script src="http://www.mamicode.com/~/Scripts/OpenLayers-demo/build/ol.js"></script>
  8 <script src="http://www.mamicode.com/~/Scripts/jquery-1.10.2.min.js"></script>
  9 <script src="http://www.mamicode.com/~/Scripts/map/mapzoomtool.js" charset="gb2312"></script>
 10 <link href="http://www.mamicode.com/~/Content/mapCtrlsstyles.css" rel="stylesheet" />
 11 <link href="http://www.mamicode.com/~/Content/resources/KitchenSink-all.css" rel="stylesheet" />
 12 <script src="http://www.mamicode.com/~/Scripts/ext-all.js"></script>
 13 <style type="text/css"> 
 14 #map { 
 15 width: 100%; 
 16 height: 100%; 
 17 position: absolute; 
 18 } 
 19 
 20 #menu { 
 21 float: left; 
 22 position: absolute; 
 23 bottom: 10px; 
 24 left: 10px; 
 25 z-index: 2000; 
 26 } 
 27 
 28 .checkbox { 
 29 left: 20px; 
 30 } 
 31 /** 
 32 * 提示框的样式信息 
 33 */ 
 34 .tooltip { 
 35 position: relative; 
 36 background: rgba(0, 0, 0, 0.5); 
 37 border-radius: 4px; 
 38 color: white; 
 39 padding: 4px 8px; 
 40 opacity: 0.7; 
 41 white-space: nowrap; 
 42 } 
 43 
 44 .tooltip-measure { 
 45 opacity: 1; 
 46 font-weight: bold; 
 47 } 
 48 
 49 .tooltip-static { 
 50 background-color: #ffffff; 
 51 color: black; 
 52 border: 1px solid white; 
 53 } 
 54 
 55 .tooltip-measure:before, 
 56 .tooltip-static:before { 
 57 border-top: 6px solid rgba(0, 0, 0, 0.5); 
 58 border-right: 6px solid transparent; 
 59 border-left: 6px solid transparent; 
 60 content: ""; 
 61 position: absolute; 
 62 bottom: -6px; 
 63 margin-left: -7px; 
 64 left: 50%; 
 65 } 
 66 
 67 .tooltip-static:before { 
 68 border-top-color: #ffffff; 
 69 } 
 70 
 71 #scalebar { 
 72 float: left; 
 73 margin-bottom: 10px; 
 74 } 
 75 </style> 
 76 <script type="text/javascript"> 
 77 $(function () { 
 78 //初始化地图 
 79 var map = new ol.Map({ 
 80 target: ‘map‘, 
 81 layers: [ 
 82 new ol.layer.Tile({ 
 83 source:new ol.source.OSM() 
 84 }) 
 85 ], 
 86 view: new ol.View({ 
 87 center: new ol.proj.fromLonLat([114.4250, 23.0890]), 
 88 zoom: 18, 
 89 maxZoom: 20 
 90 }) 
 91 }); 
 92 
 93 //定义矢量数据源 
 94 var source = new ol.source.Vector(); 
 95 //定义矢量图层 
 96 var vector = new ol.layer.Vector({ 
 97 source: source, 
 98 style: new ol.style.Style({ 
 99 fill: new ol.style.Fill({ 
100 color:‘rgba(255,255,255,0.2)‘ 
101 }), 
102 stroke: new ol.style.Stroke({ 
103 color: ‘#e21e0a‘, 
104 width:2 
105 }), 
106 image: new ol.style.Circle({ 
107 radius: 5, 
108 fill: new ol.style.Fill({ 
109 color:‘#ffcc33‘ 
110 }) 
111 }) 
112 }) 
113 }); 
114 //将矢量图层添加到地图中 
115 map.addLayer(vector); 
116 
117 //添加比例尺控件 
118 var scaleLineControl = new ol.control.ScaleLine({ 
119 units: ‘metric‘, 
120 target: ‘scalebar‘, 
121 className: ‘ol-scale-line‘ 
122 }); 
123 map.addControl(scaleLineControl); 
124 
125 
126 //创建一个WGS84球体对象 
127 var wgs84Sphere = new ol.Sphere(6378137); 
128 //创建一个当前要绘制的对象 
129 var sketch = new ol.Feature(); 
130 //创建一个帮助提示框对象 
131 var helpTooltipElement; 
132 //创建一个帮助提示信息对象 
133 var helpTooltip; 
134 //创建一个测量提示框对象 
135 var measureTooltipElement; 
136 //创建一个测量提示信息对象 
137 var measureTooltip; 
138 //继续绘制多边形的提示信息 
139 var continuePolygonMsg = ‘Click to continue drawing the polygon‘; 
140 //继续绘制线段的提示信息 
141 var continueLineMsg = ‘Click to continue drawing the line‘; 
142 
143 //鼠标移动触发的函数 
144 var pointerMoveHandler = function (evt) { 
145 //Indicates if the map is currently being dragged. 
146 //Only set for POINTERDRAG and POINTERMOVE events. Default is false. 
147 //如果是平移地图则直接结束 
148 if (evt.dragging) { 
149 return; 
150 } 
151 //帮助提示信息 
152 var helpMsg = ‘Click to start drawing‘; 
153 
154 if (sketch) { 
155 //Get the feature‘s default geometry. 
156 //A feature may have any number of named geometries. 
157 //获取绘图对象的几何要素 
158 var geom = sketch.getGeometry(); 
159 //如果当前绘制的几何要素是多边形,则将绘制提示信息设置为多边形绘制提示信息 
160 //如果当前绘制的几何要素是多线段,则将绘制提示信息设置为多线段绘制提示信息 
161 if (geom instanceof ol.geom.Polygon) { 
162 helpMsg = continuePolygonMsg; 
163 } else if (geom instanceof ol.geom.LineString) { 
164 helpMsg = continueLineMsg; 
165 } 
166 } 
167 //设置帮助提示要素的内标签为帮助提示信息 
168 helpTooltipElement.innerHTML = helpMsg; 
169 //设置帮助提示信息的位置 
170 //The coordinate in view projection corresponding to the original browser event. 
171 helpTooltip.setPosition(evt.coordinate); 
172 //移除帮助提示要素的隐藏样式 
173 $(helpTooltipElement).removeClass(‘hidden‘); 
174 }; 
175 
176 //触发pointermove事件 
177 map.on(‘pointermove‘, pointerMoveHandler); 
178 
179 //当鼠标移除地图视图的时为帮助提示要素添加隐藏样式 
180 $(map.getViewport()).on(‘mouseout‘, function () { 
181 $(helpTooltipElement).addClass(‘hidden‘); 
182 }); 
183 
184 //获取大地测量复选框 
185 var geodesicCheckbox = document.getElementById(‘geodesic‘); 
186 //获取类型 
187 var typeSelect = document.getElementById(‘type‘); 
188 //定义一个交互式绘图对象 
189 var draw; 
190 
191 //添加交互式绘图对象的函数 
192 function addInteraction() { 
193 // 获取当前选择的绘制类型 
194 var type = typeSelect.value =http://www.mamicode.com/= ‘area‘ ? ‘Polygon‘ : ‘LineString‘; 
195 //创建一个交互式绘图对象 
196 draw = new ol.interaction.Draw({ 
197 //绘制的数据源 
198 source: source, 
199 //绘制类型 
200 type: type, 
201 //样式 
202 style: new ol.style.Style({ 
203 fill: new ol.style.Fill({ 
204 color:‘rgba(255,255,255,0.2)‘ 
205 }), 
206 stroke: new ol.style.Stroke({ 
207 color: ‘rgba(0,0,0,0.5)‘, 
208 lineDash: [10, 10], 
209 width:2 
210 }), 
211 image: new ol.style.Circle({ 
212 radius: 5, 
213 stroke: new ol.style.Stroke({ 
214 color:‘rgba(0,0,0,0.7)‘ 
215 }), 
216 fill: new ol.style.Fill({ 
217 color: ‘rgba(255,255,255,0.2)‘ 
218 }) 
219 }) 
220 }) 
221 }); 
222 //将交互绘图对象添加到地图中 
223 map.addInteraction(draw); 
224 
225 //创建测量提示框 
226 createMeasureTooltip(); 
227 //创建帮助提示框 
228 createHelpTooltip(); 
229 
230 //定义一个事件监听 
231 var listener; 
232 //定义一个控制鼠标点击次数的变量 
233 var count = 0; 
234 //绘制开始事件 
235 draw.on(‘drawstart‘, function (evt) { 
236 //The feature being drawn. 
237 sketch = evt.feature; 
238 //提示框的坐标 
239 var tooltipCoord = evt.coordinate; 
240 //监听几何要素的change事件 
241 //Increases the revision counter and dispatches a ‘change‘ event. 
242 
243 listener = sketch.getGeometry().on(‘change‘, function (evt) { 
244 //The event target. 
245 //获取绘制的几何对象 
246 var geom = evt.target; 
247 //定义一个输出对象,用于记录面积和长度 
248 var output; 
249 if (geom instanceof ol.geom.Polygon) { 
250 map.removeEventListener(‘singleclick‘); 
251 map.removeEventListener(‘dblclick‘); 
252 //输出多边形的面积 
253 output = formatArea(geom); 
254 //Return an interior point of the polygon. 
255 //获取多变形内部点的坐标 
256 tooltipCoord = geom.getInteriorPoint().getCoordinates(); 
257 } else if (geom instanceof ol.geom.LineString) { 
258 //输出多线段的长度 
259 output = formatLength(geom); 
260 //Return the last coordinate of the geometry. 
261 //获取多线段的最后一个点的坐标 
262 tooltipCoord = geom.getLastCoordinate(); 
263 } 
264 
265 //设置测量提示框的内标签为最终输出结果 
266 measureTooltipElement.innerHTML = output; 
267 //设置测量提示信息的位置坐标 
268 measureTooltip.setPosition(tooltipCoord); 
269 }); 
270 
271 //地图单击事件 
272 map.on(‘singleclick‘, function (evt) { 
273 //设置测量提示信息的位置坐标,用来确定鼠标点击后测量提示框的位置 
274 measureTooltip.setPosition(evt.coordinate); 
275 //如果是第一次点击,则设置测量提示框的文本内容为起点 
276 if (count == 0) { 
277 measureTooltipElement.innerHTML = "起点"; 
278 } 
279 //根据鼠标点击位置生成一个点 
280 var point = new ol.geom.Point(evt.coordinate); 
281 //将该点要素添加到矢量数据源中 
282 source.addFeature(new ol.Feature(point)); 
283 //更改测量提示框的样式,使测量提示框可见 
284 measureTooltipElement.className = ‘tooltip tooltip-static‘; 
285 //创建测量提示框 
286 createMeasureTooltip(); 
287 //点击次数增加 
288 count++; 
289 }); 
290 
291 //地图双击事件 
292 map.on(‘dblclick‘, function (evt) { 
293 //根据 
294 var point = new ol.geom.Point(evt.coordinate); 
295 source.addFeature(new ol.Feature(point)); 
296 }); 
297 }, this); 
298 //绘制结束事件 
299 draw.on(‘drawend‘, function (evt) { 
300 count = 0; 
301 //设置测量提示框的样式 
302 measureTooltipElement.className = ‘tooltip tooltip-static‘; 
303 //Set the offset for this overlay. 
304 //设置偏移量 
305 measureTooltip.setOffset([0, -7]); 
306 //清空绘制要素 
307 sketch = null; 
308 //清空测量提示要素 
309 measureTooltipElement = null; 
310 //创建测量提示框 
311 createMeasureTooltip(); 
312 //Removes an event listener using the key returned by on() or once(). 
313 //移除事件监听 
314 ol.Observable.unByKey(listener); 
315 //移除地图单击事件 
316 map.removeEventListener(‘singleclick‘); 
317 }, this); 
318 } 
319 //创建帮助提示框 
320 function createHelpTooltip() { 
321 //如果已经存在帮助提示框则移除 
322 if (helpTooltipElement) { 
323 helpTooltipElement.parentNode.removeChild(helpTooltipElement); 
324 } 
325 //创建帮助提示要素的div 
326 helpTooltipElement = document.createElement(‘div‘); 
327 //设置帮助提示要素的样式 
328 helpTooltipElement.className = ‘tooltip hidden‘; 
329 //创建一个帮助提示的覆盖标注 
330 helpTooltip = new ol.Overlay({ 
331 element: helpTooltipElement, 
332 offset: [15, 0], 
333 positioning:‘center-left‘ 
334 }); 
335 //将帮助提示的覆盖标注添加到地图中 
336 map.addOverlay(helpTooltip); 
337 } 
338 //创建测量提示框 
339 function createMeasureTooltip() { 
340 //创建测量提示框的div 
341 measureTooltipElement = document.createElement(‘div‘); 
342 measureTooltipElement.setAttribute(‘id‘,‘lengthLabel‘); 
343 //设置测量提示要素的样式 
344 measureTooltipElement.className = ‘tooltip tooltip-measure‘; 
345 //创建一个测量提示的覆盖标注 
346 measureTooltip = new ol.Overlay({ 
347 element: measureTooltipElement, 
348 offset: [0, -15], 
349 positioning:‘bottom-center‘ 
350 }); 
351 //将测量提示的覆盖标注添加到地图中 
352 map.addOverlay(measureTooltip); 
353 } 
354 //测量类型发生改变时触发事件 
355 typeSelect.onchange = function () { 
356 //移除之前的绘制对象 
357 map.removeInteraction(draw); 
358 //重新进行绘制 
359 addInteraction(); 
360 }; 
361 
362 //格式化测量长度 
363 var formatLength = function (line) { 
364 //定义长度变量 
365 var length; 
366 //如果大地测量复选框被勾选,则计算球面距离 
367 if (geodesicCheckbox.checked) { 
368 //Return the coordinates of the linestring. 
369 //获取坐标串 
370 var coordinates = line.getCoordinates(); 
371 //初始长度为0 
372 length = 0; 
373 //获取源数据的坐标系 
374 var sourceProj = map.getView().getProjection(); 
375 //进行点的坐标转换 
376 for (var i = 0; i < coordinates.length - 1; i++) { 
377 //第一个点 
378 var c1 = ol.proj.transform(coordinates[i], sourceProj, ‘EPSG:4326‘); 
379 //第二个点 
380 var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, ‘EPSG:4326‘); 
381 //获取转换后的球面距离 
382 //Returns the distance from c1 to c2 using the haversine formula. 
383 length += wgs84Sphere.haversineDistance(c1,c2); 
384 } 
385 } else { 
386 //Return the length of the linestring on projected plane. 
387 //计算平面距离 
388 length = Math.round(line.getLength() * 100) / 100; 
389 } 
390 //定义输出变量 
391 var output; 
392 //如果长度大于1000,则使用km单位,否则使用m单位 
393 if (length > 1000) { 
394 output = (Math.round(length / 1000 * 100) / 100) + ‘ ‘ + ‘km‘; //换算成KM单位 
395 } else { 
396 output = (Math.round(length * 100) / 100) + ‘ ‘ + ‘m‘; //m为单位 
397 } 
398 return output; 
399 }; 
400 
401 //格式化测量面积 
402 var formatArea = function (polygon) { 
403 //定义面积变量 
404 var area; 
405 //如果大地测量复选框被勾选,则计算球面面积 
406 if (geodesicCheckbox.checked) { 
407 //获取初始坐标系 
408 var sourceProj = map.getView().getProjection(); 
409 //Make a complete copy of the geometry. 
410 //Transform each coordinate of the geometry from one coordinate reference system to another. 
411 //The geometry is modified in place. For example, a line will be transformed to a line and a circle to a circle. 
412 //If you do not want the geometry modified in place, first clone() it and then use this function on the clone. 
413 //克隆该几何对象然后转换坐标系 
414 var geom = polygon.clone().transform(sourceProj, ‘EPSG:4326‘); 
415 //Return the Nth linear ring of the polygon geometry. 
416 //Return null if the given index is out of range. 
417 //The exterior linear ring is available at index 0 and the interior rings at index 1 and beyond. 
418 //获取多边形的坐标系 
419 var coordinates = geom.getLinearRing(0).getCoordinates(); 
420 //Returns the geodesic area for a list of coordinates. 
421 //获取球面面积 
422 area = Math.abs(wgs84Sphere.geodesicArea(coordinates)); 
423 } else { 
424 //获取平面面积 
425 area = polygon.getArea(); 
426 } 
427 //定义输出变量 
428 var output; 
429 //当面积大于10000时,转换为平方千米,否则为平方米 
430 if (area > 10000) { 
431 output = (Math.round(area/1000000*100)/100) + ‘ ‘ + ‘km<sup>2</sup>‘; 
432 } else { 
433 output = (Math.round(area*100)/100) + ‘ ‘ + ‘m<sup>2</sup>‘; 
434 } 
435 return output; 
436 }; 
437 //添加交互绘图对象 
438 addInteraction(); 
439 }); 
440 </script> 
441 </head> 
442 <body> 
443 <div id="map"> 
444 <div id="menu"> 
445 <label>测量类型选择</label> 
446 <select id="type"> 
447 <option value="http://www.mamicode.com/length">长度</option> 
448 <option value="http://www.mamicode.com/area">面积</option> 
449 </select> 
450 <label class="checkbox"><input type="checkbox" id="geodesic" />使用大地测量</label> 
451 </div> 
452 </div> 
453 <div id="scalebar"></div> 
454 </body> 
455 </html>

 

openlayers3 实现测距 面积