Openlayers实现测量功能


Posted in Javascript onSeptember 25, 2020

本文实例为大家分享了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>

效果图:

Openlayers实现测量功能

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

源代码地址:测量实例

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

Javascript 相关文章推荐
javascript打开新窗口同时关闭旧窗口
Jan 16 Javascript
JavaScript高级程序设计 DOM学习笔记
Sep 10 Javascript
IE6-IE9不支持table.innerHTML的解决方法分享
Sep 14 Javascript
用原生JavaScript实现jQuery的$.getJSON的解决方法
May 03 Javascript
jQuery选择器中含有空格的使用示例及注意事项
Aug 25 Javascript
js阻止默认事件与js阻止事件冒泡示例分享 js阻止冒泡事件
Jan 27 Javascript
JavaScript中的splice()方法使用详解
Jun 09 Javascript
理解javascript中的严格模式
Feb 01 Javascript
Vue filter格式化时间戳时间成标准日期格式的方法
Sep 16 Javascript
JS基于ES6新特性async await进行异步处理操作示例
Feb 02 Javascript
详解使用JWT实现单点登录(完全跨域方案)
Aug 02 Javascript
微信小程序实现页面左右滑动
Nov 16 Javascript
openlayers4.6.5实现距离量测和面积量测
Sep 25 #Javascript
JQuery Ajax如何实现注册检测用户名
Sep 25 #jQuery
Openlayers测量距离与面积的实现方法
Sep 25 #Javascript
基于JS实现操作成功之后自动跳转页面
Sep 25 #Javascript
OpenLayers3实现测量功能
Sep 25 #Javascript
OpenLayers3实现地图鹰眼以及地图比例尺的添加
Sep 25 #Javascript
OpenLayers3实现鼠标移动显示坐标
Sep 25 #Javascript
You might like
php判断GIF图片是否为动画的方法
2020/09/04 PHP
Laravel框架表单验证详解
2014/09/04 PHP
在PHP中使用FastCGI解析漏洞及修复方案
2015/11/10 PHP
Smarty环境配置与使用入门教程
2016/05/11 PHP
PHP中“=&gt;
2019/03/01 PHP
js onclick事件传参讲解
2013/11/06 Javascript
jquery map方法使用示例
2014/04/23 Javascript
[原创]jQuery常用的4种加载方式分析
2016/07/25 Javascript
在windows上用nodejs搭建静态文件服务器的简单方法
2016/08/11 NodeJs
微信开发 微信授权详解
2016/10/21 Javascript
详解在Vue中通过自定义指令获取dom元素
2017/03/04 Javascript
使用jQuery监听扫码枪输入并禁止手动输入的实现方法(推荐)
2017/03/21 jQuery
Underscore之Array_动力节点Java学院整理
2017/07/10 Javascript
关于AngularJS中ng-repeat不更新视图的解决方法
2018/09/30 Javascript
使用Webpack 搭建 Vue3 开发环境过程详解
2020/07/28 Javascript
nodejs中内置模块fs,path常见的用法说明
2020/11/07 NodeJs
[47:50]Secret vs VP 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
使用Python脚本将文字转换为图片的实例分享
2015/08/29 Python
Python常见字符串操作函数小结【split()、join()、strip()】
2018/02/02 Python
详解python while 函数及while和for的区别
2018/09/07 Python
在python中安装basemap的教程
2018/09/20 Python
Django获取该数据的上一条和下一条方法
2019/08/12 Python
Python实现串口通信(pyserial)过程解析
2019/09/25 Python
python的faker库用法
2019/11/28 Python
python实现12306登录并保存cookie的方法示例
2019/12/17 Python
Django实现内容缓存实例方法
2020/06/30 Python
如何把python项目部署到linux服务器
2020/08/26 Python
韩都衣舍天猫官方旗舰店:天猫女装销售总冠军
2017/10/10 全球购物
本科生详细的自我评价
2013/09/19 职场文书
公司任命书模板
2014/06/06 职场文书
2014县委书记四风对照检查材料思想汇报
2014/09/21 职场文书
县委务虚会发言材料
2014/10/20 职场文书
优秀班主任事迹材料
2014/12/16 职场文书
优秀党员事迹材料
2014/12/18 职场文书
2016年大学生就业指导课心得体会
2015/10/09 职场文书
python如何利用cv2模块读取显示保存图片
2021/06/04 Python