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 相关文章推荐
用一段js程序来实现动画功能
Mar 06 Javascript
javascript 继承实现方法
Aug 26 Javascript
网页自动跳转代码收集
Sep 27 Javascript
可简单避免的三个JS发布错误的详细介绍
Aug 02 Javascript
jQuery封装的获取Url中的Get参数示例
Nov 26 Javascript
alert和confirm功能介绍
May 21 Javascript
利用javascript实现全部删或清空所选的操作
May 27 Javascript
jQuery事件绑定on()与弹窗实现代码
Apr 28 Javascript
两种JavaScript的AES加密方式(可与Java相互加解密)
Aug 02 Javascript
微信小程序 教程之数据绑定
Oct 18 Javascript
微信开发之调起摄像头、本地展示图片、上传下载图片实例
Dec 08 Javascript
vue+canvas实现拼图小游戏
Sep 18 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
laravel 如何实现引入自己的函数或类库
2019/10/15 PHP
PhpStorm的使用教程(本地运行PHP+远程开发+快捷键)
2020/03/26 PHP
多个表单中如何获得这个文件上传的网址实现js代码
2013/03/25 Javascript
JS判断数组中是否有重复值得三种实用方法
2013/08/16 Javascript
jQuery实现列表自动循环滚动鼠标悬停时停止滚动
2013/09/06 Javascript
Tab切换组件(选项卡功能)实例代码
2013/11/21 Javascript
Eclipse配置Javascript开发环境图文教程
2015/01/29 Javascript
Google 地图获取API Key详细教程
2016/08/06 Javascript
JS组件系列之使用HTML标签的data属性初始化JS组件
2016/09/14 Javascript
Node.js制作简单聊天室
2017/01/12 Javascript
jQuery实现select下拉框获取当前选中文本、值、索引
2017/05/08 jQuery
vue 实现通过手机发送短信验证码注册功能
2018/04/19 Javascript
Angular6中使用Swiper的方法示例
2018/07/09 Javascript
JavaScript设计模式之工厂模式和抽象工厂模式定义与用法分析
2018/07/26 Javascript
动态内存分配导致影响Javascript性能的问题
2018/12/18 Javascript
JavaScript实现shuffle数组洗牌操作示例
2019/01/03 Javascript
改变layer confirm弹窗按钮的颜色方法
2019/09/12 Javascript
Vue页面刷新记住页面状态的实现
2019/12/27 Javascript
使用webpack搭建vue环境的教程详解
2019/12/31 Javascript
微信小程序实现简单的select下拉框
2020/11/23 Javascript
Python加pyGame实现的简单拼图游戏实例
2015/05/15 Python
使用Python的Twisted框架编写非阻塞程序的代码示例
2016/05/25 Python
Python 实现将数组/矩阵转换成Image类
2020/01/09 Python
Python常见反爬虫机制解决方案
2020/06/01 Python
Python3.9最新版下载与安装图文教程详解(Windows系统为例)
2020/11/28 Python
Python使用pyenv实现多环境管理
2021/02/05 Python
CSS伪类与CSS伪元素的区别及由来具体说明
2012/12/07 HTML / CSS
HTML5 Plus 实现手机APP拍照或相册选择图片上传功能
2016/07/13 HTML / CSS
Dune London官网:英国著名奢华鞋履品牌
2017/11/30 全球购物
伦敦一家西班牙童装精品店:La Coqueta
2018/02/02 全球购物
2014年教师政治学习材料
2014/06/02 职场文书
协议书范文
2015/01/27 职场文书
党员个人承诺书
2015/04/27 职场文书
2015年小学语文教师工作总结
2015/10/23 职场文书
《雪地里的小画家》教学反思
2016/02/16 职场文书
七年级作文之游记
2019/12/11 职场文书