Openlayers实现测量功能
程序员文章站
2022-07-06 15:54:32
本文实例为大家分享了openlayers实现测量的具体代码,供大家参考,具体内容如下由于公司项目需要使用到openlayers,就开始学习了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: ' '//未定义坐标标记 }); //添加鼠标位置控件 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发布的一个组合图层,可以自行定义。
源代码地址:测量实例
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。