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 相关文章推荐
初探jquery——表单应用范例
Feb 20 Javascript
JavaScript中的其他对象
Jan 16 Javascript
Jquery提交表单 Form.js官方插件介绍
Mar 01 Javascript
利用浏览器全屏api实现js全屏
Jan 16 Javascript
js中直接声明一个对象的方法
Aug 10 Javascript
window.open()实现post传递参数
Mar 12 Javascript
jQuery实现磁力图片跟随效果完整示例
Sep 16 Javascript
Ajax+FormData+javascript实现无刷新表单信息提交
Oct 24 Javascript
老生常谈jquery id选择器和class选择器的区别
Feb 12 Javascript
bootstrap可编辑下拉框jquery.editable-select
Oct 12 jQuery
Vue CLI2升级至Vue CLI3的方法步骤
May 20 Javascript
HTML元素拖拽功能实现的完整实例
Dec 04 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的FTP学习(三)
2006/10/09 PHP
PHP 文件上传进度条的两种实现方法的代码
2007/11/25 PHP
php Sql Server连接失败问题及解决办法
2009/08/07 PHP
PHP分多步骤填写发布信息的简单方法实例代码
2012/09/23 PHP
php中unlink()、mkdir()、rmdir()等方法的使用介绍
2012/12/21 PHP
php二维数组排序详解
2013/11/06 PHP
php中filter函数验证、过滤用户输入的数据
2014/01/13 PHP
php跨服务器访问方法小结
2015/05/12 PHP
thinkphp5 加载静态资源路径与常量的方法
2017/12/24 PHP
PHP命名空间简单用法示例
2018/12/28 PHP
php新建文件的方法实例
2019/09/26 PHP
jquery ajax 检测用户注册时用户名是否存在
2009/11/03 Javascript
IE bug table元素的innerHTML
2010/01/11 Javascript
JS实现随页面滚动显示/隐藏窗口固定位置元素
2016/02/26 Javascript
利用AngularJs实现京东首页轮播图效果
2016/09/08 Javascript
纯原生js实现table表格的增删
2017/01/05 Javascript
[01:03]PWL开团时刻DAY6——别打我
2020/11/05 DOTA
python使用PIL缩放网络图片并保存的方法
2015/04/24 Python
Tornado协程在python2.7如何返回值(实现方法)
2017/06/22 Python
PHP统计代码行数的小代码
2019/09/19 Python
python requests抓取one推送文字和图片代码实例
2019/11/04 Python
解决import tensorflow as tf 出错的原因
2020/04/16 Python
Python如何实现邮件功能
2020/05/27 Python
美国在线奢侈品寄售商店:Luxury Garage Sale
2018/08/19 全球购物
西班牙著名的珠宝首饰品牌:P D PAOLA
2018/09/15 全球购物
Python里面如何拷贝一个对象
2014/02/17 面试题
车间组长岗位职责
2013/12/20 职场文书
2014年幼儿园元旦活动方案
2014/02/13 职场文书
红色旅游心得体会
2014/09/03 职场文书
大学生助学金感谢信
2015/01/21 职场文书
2015年依法治校工作总结
2015/07/27 职场文书
创业计划之特色精品店
2019/08/12 职场文书
22句经典语录:送给优柔寡断和胡思乱想的朋友们
2019/12/13 职场文书
使用Html+Css实现简易导航栏功能(导航栏遇到鼠标切换背景颜色)
2021/04/07 HTML / CSS
Python基本知识点总结
2022/04/07 Python
详解ZABBIX监控ESXI主机的问题
2022/06/21 Servers