Openlayers测量距离与面积的实现方法


Posted in Javascript onSeptember 25, 2020

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

1、地图测量功能

一般的地图的测量功能主要表现在两个方面,一是测量距离,一是测量面积;面积的测量是根据鼠标绘制的范围,通过地理坐标系的转换而计算出实际面积大小,距离的测量是根据鼠标在地图上绘制的点,实时计算出两点之间的实际距离,下面我们就在Openlayers3中来实现这一功能;

2、代码实现

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title></title>
 <script src="../lib/ol/ol.js"></script>
 <link href="../css/ol.css" rel="stylesheet" />
 <script src="../lib/jquery/jquery-1.8.2.js"></script>
 <link href="../css/bootstrap.min.css" rel="stylesheet" />
 <script src="../lib/bootstrap/bootstrap.min.js"></script>
 <style type="text/css">
  #map {
   width: 100%;
   height: 100%;
   position: absolute;
  }
 
  #menu {
   float: left;
   position: absolute;
   bottom: 10px;
   left: 10px;
   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>
 <script type="text/javascript">
  $(function () {
   //初始化地图
   var map = new ol.Map({
    target: 'map',
    layers: [
     new ol.layer.Tile({
      source:new ol.source.OSM()
     })
    ],
    view: new ol.View({
     center: new ol.proj.fromLonLat([114.4250, 23.0890]),
     zoom: 18,
     maxZoom: 20
    })
   });
 
   //定义矢量数据源
   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);
 
 
   //创建一个WGS84球体对象
   var wgs84Sphere = new ol.Sphere(6378137);
   //创建一个当前要绘制的对象
   var sketch = new ol.Feature();
   //创建一个帮助提示框对象
   var helpTooltipElement;
   //创建一个帮助提示信息对象
   var helpTooltip;
   //创建一个测量提示框对象
   var measureTooltipElement;
   //创建一个测量提示信息对象
   var measureTooltip;
   //继续绘制多边形的提示信息
   var continuePolygonMsg = 'Click to continue drawing the polygon';
   //继续绘制线段的提示信息
   var continueLineMsg = 'Click to continue drawing the line';
 
   //鼠标移动触发的函数
   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 = 'Click to start drawing';
 
    if (sketch) {
     //Get the feature's default geometry. 
     //A feature may have any number of named geometries.
     //获取绘图对象的几何要素
     var geom = sketch.getGeometry();
     //如果当前绘制的几何要素是多边形,则将绘制提示信息设置为多边形绘制提示信息
     //如果当前绘制的几何要素是多线段,则将绘制提示信息设置为多线段绘制提示信息
     if (geom instanceof ol.geom.Polygon) {
      helpMsg = continuePolygonMsg;
     } else if (geom instanceof ol.geom.LineString) {
      helpMsg = continueLineMsg;
     }
    }
    //设置帮助提示要素的内标签为帮助提示信息
    helpTooltipElement.innerHTML = helpMsg;
    //设置帮助提示信息的位置
    //The coordinate in view projection corresponding to the original browser event.
    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);
       //Return an interior point of the polygon.
       //获取多变形内部点的坐标
       tooltipCoord = geom.getInteriorPoint().getCoordinates();
      } else if (geom instanceof ol.geom.LineString) {
       //输出多线段的长度
       output = formatLength(geom);
       //Return the last coordinate of the geometry.
       //获取多线段的最后一个点的坐标
       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';
     //Set the offset for this overlay.
     //设置偏移量
     measureTooltip.setOffset([0, -7]);
     //清空绘制要素
     sketch = null;
     //清空测量提示要素
     measureTooltipElement = null;
     //创建测量提示框
     createMeasureTooltip();
     //Removes an event listener using the key returned by on() or once().
     //移除事件监听
     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) {
     //Return the coordinates of the linestring.
     //获取坐标串
     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 {
     //Return the length of the linestring on projected plane.
     //计算平面距离
     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();
     //Make a complete copy of the geometry.
     //Transform each coordinate of the geometry from one coordinate reference system to another. 
     //The geometry is modified in place. For example, a line will be transformed to a line and a circle to a circle.
     //If you do not want the geometry modified in place, first clone() it and then use this function on the clone.
     //克隆该几何对象然后转换坐标系
     var geom = polygon.clone().transform(sourceProj, 'EPSG:4326');
     //Return the Nth linear ring of the polygon geometry. 
     //Return null if the given index is out of range. 
     //The exterior linear ring is available at index 0 and the interior rings at index 1 and beyond.
     //获取多边形的坐标系
     var coordinates = geom.getLinearRing(0).getCoordinates();
     //Returns the geodesic area for a list of coordinates.
     //获取球面面积
     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>
</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"><input type="checkbox" id="geodesic" />使用大地测量</label>
  </div>
 </div>
 <div id="scalebar"></div>
</body>
</html>

3、结果展示

测量距离

Openlayers测量距离与面积的实现方法

测量面积

Openlayers测量距离与面积的实现方法

此外,还能勾选使用大地测量的复选框,进行球面距离和面积的测量

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

Javascript 相关文章推荐
javascript 获取页面的高度及滚动条的位置的代码
May 06 Javascript
使用js画图之正弦曲线
Jan 12 Javascript
JavaScript将XML转成JSON的方法
Mar 12 Javascript
Js数组排序函数sort()介绍
Jun 08 Javascript
详解AngularJS中的filter过滤器用法
Jan 04 Javascript
JQ选择器_选择同类元素的第N个子元素的实现方法
Sep 08 Javascript
AngularJS实现DOM元素的显示与隐藏功能
Nov 22 Javascript
JavaScript获取URL参数的方法之一
Mar 24 Javascript
webpack踩坑之路图片的路径与打包
Sep 05 Javascript
2种简单的js倒计时方式
Oct 20 Javascript
AngularJS自定义表单验证功能实例详解
Aug 24 Javascript
vue实现多组关键词对应高亮显示功能
Jul 25 Javascript
基于JS实现操作成功之后自动跳转页面
Sep 25 #Javascript
OpenLayers3实现测量功能
Sep 25 #Javascript
OpenLayers3实现地图鹰眼以及地图比例尺的添加
Sep 25 #Javascript
OpenLayers3实现鼠标移动显示坐标
Sep 25 #Javascript
js获取url页面id,也就是最后的数字文件名
Sep 25 #Javascript
OpenLayers3实现图层控件功能
Sep 25 #Javascript
OpenLayers实现图层切换控件
Sep 25 #Javascript
You might like
php学习 字符串课件
2008/06/15 PHP
重新封装zend_soap实现http连接安全认证的php代码
2011/01/12 PHP
php实现微信发红包
2015/12/05 PHP
[原创]PHP实现逐行删除文件右侧空格的方法
2015/12/25 PHP
Laravel 队列使用的实现
2019/01/08 PHP
关于Curl在Swoole协程中的解决方案详析
2019/09/12 PHP
laravel框架中控制器的创建和使用方法分析
2019/11/23 PHP
CL vs ForZe BO5 第一场 2.13
2021/03/10 DOTA
javascript中普通函数的使用介绍
2013/12/19 Javascript
jquery取消选择select下拉框示例代码
2014/02/22 Javascript
jQuery实现的手机发送验证码倒计时效果代码分享
2015/08/24 Javascript
javascript中日期函数new Date()的浏览器兼容性问题
2015/09/05 Javascript
webpack 4.0.0-beta.0版本新特性介绍
2018/02/10 Javascript
vue2.0实现移动端的输入框实时检索更新列表功能
2018/05/08 Javascript
nodejs和react实现即时通讯简易聊天室功能
2019/08/21 NodeJs
Vue如何获取数据列表展示
2019/12/11 Javascript
JS如何实现网站中PC端和手机端自动识别并跳转对应的代码
2020/01/08 Javascript
JS实现简单移动端鼠标拖拽
2020/07/23 Javascript
[03:07]完美世界DOTA2联赛PWL DAY10 决赛集锦
2020/11/11 DOTA
python求pi的方法
2014/10/08 Python
Python实现将数据库一键导出为Excel表格的实例
2016/12/30 Python
python实现简单淘宝秒杀功能
2018/05/03 Python
Selenium chrome配置代理Python版的方法
2018/11/29 Python
Python网页正文转换语音文件的操作方法
2018/12/09 Python
java判断三位数的实例讲解
2019/06/10 Python
pyqt 实现在Widgets中显示图片和文字的方法
2019/06/13 Python
python如何导出微信公众号文章方法详解
2020/08/31 Python
python与js主要区别点总结
2020/09/13 Python
欧姆龙医疗保健与医疗产品:Omron Healthcare
2020/02/10 全球购物
天游软件面试
2013/11/23 面试题
静心口服夜广告词
2014/03/20 职场文书
优秀应届毕业生自荐书
2014/06/29 职场文书
2014客服代表实习自我鉴定
2014/09/18 职场文书
MySQL的安装与配置详细教程
2021/06/26 MySQL
Java8 Stream API 提供了一种高效且易于使用的处理数据的方式
2022/04/13 Java/Android
Go中使用gjson来操作JSON数据的实现
2022/08/14 Golang