OpenLayers3实现测量功能


Posted in Javascript onSeptember 25, 2020

本文实例为大家分享了OpenLayers3实现测量功能的具体代码,供大家参考,具体内容如下

1. 前言

测量功能实现面积的测量以及长度的测量。通过鼠标绘制区域以及长度来进行测量。OpenLayers 3 框架没有提供测量控件,但提供了相应的接口,需要需要基于几何对象的相应接口,结合图形绘制功能实现。

2. 实现思路

(1)新建一个网页,引用 openlayers 3 开发库、jQuery 库与 bootstrap 库,并参照前面显示地图的文章,加载 OSM 瓦片图层。
(2)在地图容器中,创建一个测量类型选择控件,进行选择距离测量与面积测量。
(3)编写代码实现测量功能。

3. 实现代码

html主要代码

<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>

测量类型控件的样式设置:

#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: #ffcc33;
      color: black;
      border: 1px solid white;
    }

    .tooltip-measure::before,
    .tooltip-static::before {
      border-top: 6px solid rgb(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: #ffcc33;
}

代码解析

上面的代码是结合 bootstrap库,使用冒泡提示框形式显示当前的测量结果,上面的样式分别设置了两种提示框的样式。

4. 实现测量功能的核心代码

(1)首先在地图上加载测量功能的绘制层,即矢量图层,就相当于,我们画画,需要纸来进行绘画,这里的矢量图层,相当于我们的纸。代码如下:

//加载测量的绘制矢量层
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: '#ffcc33', //边框颜色
    width: 2 // 边框宽度
   }),
   image: new ol.style.Circle({
    radius: 7,
    fill: new ol.style.Fill({
     color: '#ffcc33'
    })
   })
  })
 });
map.addLayer(vector);

(2)通过 addInteraction 方法实现测量功能,首先加载交互绘图控件(ol.interaction.Draw),也就是我们前面所说的画画需要的笔,在测量时根据测量类型选择绘制线段或多边形,然后分别为交互绘图控件绑定 drawstart 与 drawend 事件。在绘图开始时实时计算当前当前绘制线的长度或多边形的面积,以提示框形式显示,绘图结束时重新创建一个测量提示框显示测量结果。通过 addInteraction 函数实现绘图测量的代码:

4.1 addInteraction 函数实现绘图测量的代码:

/**
  * 切换选择测量类型(长度或面积)
  * @param {Event} e Change event.
  */
 typeSelect.onchange = function(e) {
  map.removeInteraction(draw); //移除绘制图形
  addInteraction(); //添加绘图进行测量
 };
addInteraction(); //调用加载绘制交互控件的方法,添加绘图进行测量

addInteraction()函数代码:

var geodesicCheckbox = document.getElementById('geodesic'); //测地学方式对象
var typeSelect = document.getElementById('type'); //测量类型对象
var draw; // global so we can remove it later
/**
 * 加载交互绘制控件函数 
 */
function addInteraction() {
 var type = (typeSelect.value == 'area' ? 'Polygon' : 'LineString');
 draw = new ol.interaction.Draw({
  source: source, //测量绘制层数据源
  type: /** @type {ol.geom.GeometryType} */ (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;
 //绑定交互绘制工具开始绘制的事件
 draw.on('drawstart',
  function(evt) {
   // set sketch
   sketch = evt.feature; //绘制的要素

   /** @type {ol.Coordinate|undefined} */
   var tooltipCoord = evt.coordinate; // 绘制的坐标
   //绑定change事件,根据绘制几何类型得到测量长度值或面积值,并将其设置到测量工具提示框中显示
   listener = sketch.getGeometry().on('change', function(evt) {
    var geom = evt.target; //绘制几何要素
    var output;
    if (geom instanceof ol.geom.Polygon) {
     output = formatArea( /** @type {ol.geom.Polygon} */ (geom)); //面积值
     tooltipCoord = geom.getInteriorPoint().getCoordinates(); //坐标
    } else if (geom instanceof ol.geom.LineString) {
     output = formatLength( /** @type {ol.geom.LineString} */ (geom)); //长度值
     tooltipCoord = geom.getLastCoordinate(); //坐标
    }
    measureTooltipElement.innerHTML = output; //将测量值设置到测量工具提示框中显示
    measureTooltip.setPosition(tooltipCoord); //设置测量工具提示框的显示位置
   });
  }, this);
 //绑定交互绘制工具结束绘制的事件
 draw.on('drawend',
  function(evt) {
   measureTooltipElement.className = 'tooltip tooltip-static'; //设置测量提示框的样式
   measureTooltip.setOffset([0, -7]);
   // unset sketch
   sketch = null; //置空当前绘制的要素对象
   // unset tooltip so that a new one can be created
   measureTooltipElement = null; //置空测量工具提示框对象
   createMeasureTooltip(); //重新创建一个测试工具提示框显示结果
   ol.Observable.unByKey(listener);
  }, this);
}

代码解析

首先加载绘图控件(ol.interaction.Draw),也就是我们的笔,在实例化控件时设置当前绘图要素的样式,然后分别调用 createHelpTooltop() 与 createMeasureTooltip() 创建帮助信息提示框和测量工具提示框对象;最后绑定绘图控件对象的 drawstart 与 drawend 事件,实现绘图测量功能。其中,在drawstart 事件处理函数中, 由事件对象得到当前绘制的要素(sketch),通过绘制要素的几何对象绑定 change 事件,根据事件监听的几何对象类型是线或是多边形(ol.geom.Polygon 或 ol.geom.LineString),调用 formatArea() 与 formatLength() 计算输出测量得到的面积值或长度值。

4.2 创建提示框的代码: 

/**
  *创建一个新的帮助提示框(tooltip)
  */
 function createHelpTooltip() {
  if (helpTooltipElement) {
   helpTooltipElement.parentNode.removeChild(helpTooltipElement);
  }
  helpTooltipElement = document.createElement('div');
  helpTooltipElement.className = 'tooltip hidden';
  helpTooltip = new ol.Overlay({
   element: helpTooltipElement,
   offset: [15, 0],
   positioning: 'center-left'
  });
  map.addOverlay(helpTooltip);
 }
 /**
  *创建一个新的测量工具提示框(tooltip)
  */
 function createMeasureTooltip() {
  if (measureTooltipElement) {
   measureTooltipElement.parentNode.removeChild(measureTooltipElement);
  }
  measureTooltipElement = document.createElement('div');
  measureTooltipElement.className = 'tooltip tooltip-measure';
  measureTooltip = new ol.Overlay({
   element: measureTooltipElement,
   offset: [0, -15],
   positioning: 'bottom-center'
  });
  map.addOverlay(measureTooltip);
}

代码解析

基于Openlayers 3 的 ol.Overlay 实现创建帮助信息提示框和测量工具提示框,分别通过 createHelpTooltip() 与 createMeasureTooltip() 创建帮助信息提示框和测量工具提示框, ol.Overlay j就是动态创建叠加层对象与其目标容器(div层),并将叠加层对象添加到地图容器中。

4.3 计算长度与面积的代码:

/**
  * 测量长度输出
  * @param {ol.geom.LineString} line
  * @return {string}
  */
 var formatLength = function(line) {
  var length;
  if (geodesicCheckbox.checked) { //若使用测地学方法测量
   var coordinates = line.getCoordinates(); //解析线的坐标
   length = 0;
   var sourceProj = map.getView().getProjection(); //地图数据源投影坐标系
   //通过遍历坐标计算两点之前距离,进而得到整条线的长度
   for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {
    var c1 = ol.proj.transform(coordinates[i], sourceProj, 'EPSG:4326');
    var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'EPSG:4326');
    length += wgs84Sphere.haversineDistance(c1, c2);
   }
  } else {
   length = Math.round(line.getLength() * 100) / 100; //直接得到线的长度
  }
  var output;
  if (length > 100) {
   output = (Math.round(length / 1000 * 100) / 100) + ' ' + 'km'; //换算成KM单位
  } else {
   output = (Math.round(length * 100) / 100) + ' ' + 'm'; //m为单位
  }
  return output; //返回线的长度
 };
 /**
  * 测量面积输出
  * @param {ol.geom.Polygon} polygon
  * @return {string}
  */
 var formatArea = function(polygon) {
  var area;
  if (geodesicCheckbox.checked) { //若使用测地学方法测量
   var sourceProj = map.getView().getProjection(); //地图数据源投影坐标系
   var geom = /** @type {ol.geom.Polygon} */ (polygon.clone().transform(sourceProj, 'EPSG:4326')); //将多边形要素坐标系投影为EPSG:4326
   var coordinates = geom.getLinearRing(0).getCoordinates(); //解析多边形的坐标值
   area = Math.abs(wgs84Sphere.geodesicArea(coordinates)); //获取面积
  } else {
   area = polygon.getArea(); //直接获取多边形的面积
  }
  var output;
  if (area > 10000) {
   output = (Math.round(area / 1000000 * 100) / 100) + ' ' + 'km<sup>2</sup>'; //换算成KM单位
  } else {
   output = (Math.round(area * 100) / 100) + ' ' + 'm<sup>2</sup>'; //m为单位
  }
  return output; //返回多边形的面积
 };

addInteraction(); //调用加载绘制交互控件方法,添加绘图进行测量

代码解析

上面代码通过 formatLength() 与 formatArea() 分别计算输出的长度值以及面积值。计算长度值或者面积值时可以通过两种方法进行计算,一种是使用测地学的方法基于数据的投影坐标系进行计算,另一种是调用几何对象或者多边形对象的方法直接获取值。

(3)开始画画了,分别使用map对象绑定鼠标移动事件(pointermove)和鼠标移除事件(mouseout)。

4.4 添加地图鼠标移动事件的代码:

/**
  * 当用户正在绘制多边形时的提示信息文本
  * @type {string}
  */
 var continuePolygonMsg = '单击继续绘制多边形';
 /**
  * 当用户正在绘制线时的提示信息文本
  * @type {string}
  */
 var continueLineMsg = '单击继续绘制线';

 /**
  * 鼠标移动事件处理函数
  * @param {ol.MapBrowserEvent} evt
  */
 var pointerMoveHandler = function(evt) {
  if (evt.dragging) {
   return;
  }
  /** @type {string} */
  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'); //移除帮助提示框的隐藏样式进行显示
 };
 map.on('pointermove', pointerMoveHandler); //地图容器绑定鼠标移动事件,动态显示帮助提示框内容
 //地图绑定鼠标移出事件,鼠标移出时为帮助提示框设置隐藏样式
 $(map.getViewport()).on('mouseout', function() {
  $(helpTooltipElement).addClass('hidden');
});

代码解析

鼠标移动事件(pointermove),在回调函数中,根据用户选择测量的类型,在弹窗中显示帮助提示信息,同时为地图容器绑定鼠标移除事件(mouseout),该事件发生后影藏提示框。

5. 实现效果

OpenLayers3实现测量功能

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

Javascript 相关文章推荐
表单元素事件 (Form Element Events)
Jul 17 Javascript
JQuery UI的拖拽功能实现方法小结
Mar 14 Javascript
jquery实现metro效果示例代码
Sep 06 Javascript
js导入导出excel(实例代码)
Nov 25 Javascript
JS控制页面跳转时未请求要跳转的地址怎么回事
Oct 14 Javascript
JavaScript中 this 指向问题深度解析
Feb 21 Javascript
vue.js 1.x与2.0中js实时监听input值的变化
Mar 15 Javascript
jQuery EasyUI tree增加搜索功能的实现方法
Apr 27 jQuery
JavaScript模拟文件拖选框样式v1.0的实例
Aug 04 Javascript
微信小程序module.exports模块化操作实例浅析
Dec 20 Javascript
js遍历详解(forEach, map, for, for...in, for...of)
Aug 28 Javascript
Angular 多模块项目构建过程
Feb 13 Javascript
OpenLayers3实现地图鹰眼以及地图比例尺的添加
Sep 25 #Javascript
OpenLayers3实现鼠标移动显示坐标
Sep 25 #Javascript
js获取url页面id,也就是最后的数字文件名
Sep 25 #Javascript
OpenLayers3实现图层控件功能
Sep 25 #Javascript
OpenLayers实现图层切换控件
Sep 25 #Javascript
OpenLayers3实现对地图的基本操作
Sep 28 #Javascript
vue中实现弹出层动画效果的示例代码
Sep 25 #Javascript
You might like
单位速度在实战中的运用
2020/03/04 星际争霸
php a simple smtp class
2007/11/26 PHP
使用php shell命令合并图片的代码
2011/06/23 PHP
php中get_cfg_var()和ini_get()的用法及区别
2015/03/04 PHP
PHP生成随机字符串(3种方法)
2015/09/25 PHP
PHP中CheckBox多选框上传失败的代码写法
2017/02/13 PHP
PHP getID3类的使用方法学习笔记【附getID3源码下载】
2019/10/18 PHP
javascript css在IE和Firefox中区别分析
2009/02/18 Javascript
window.onload 加载完毕的问题及解决方案(上)
2009/07/09 Javascript
使用PHP+JQuery+Ajax分页的实现
2013/04/23 Javascript
超简单JS二级、多级联动的简单实例
2014/02/18 Javascript
复制网页内容,粘贴之后自动加上网址的实现方法(脚本之家特别整理)
2014/10/16 Javascript
jQuery选择器源码解读(一):Sizzle方法
2015/03/31 Javascript
js如何改变文章的字体大小
2016/01/08 Javascript
js获取当前年月日-YYYYmmDD格式的实现代码
2016/06/01 Javascript
jQuery EasyUI学习教程之datagrid点击列表头排序
2016/07/09 Javascript
Vue项目中引入外部文件的方法(css、js、less)
2017/07/24 Javascript
node.js基于fs模块对系统文件及目录进行读写操作的方法详解
2017/11/10 Javascript
关于Mac下安装nodejs、npm和cnpm的教程
2018/04/11 NodeJs
Javascript获取某个月的天数
2018/05/30 Javascript
基于JavaScript获取url参数2种方法
2020/04/17 Javascript
python3 打开外部程序及关闭的示例
2018/11/06 Python
Python操作Mongodb数据库的方法小结
2019/09/10 Python
python子线程退出及线程退出控制的代码
2019/10/16 Python
pytorch中的inference使用实例
2020/02/20 Python
Keras模型转成tensorflow的.pb操作
2020/07/06 Python
Coccinelle官网:意大利的著名皮具品牌
2019/05/15 全球购物
介绍下java.util.Arrays类
2012/10/16 面试题
银行求职推荐信范文
2013/11/30 职场文书
最新大学职业规划书范文
2013/12/30 职场文书
员工晚婚的请假条
2014/02/08 职场文书
毕业生个人求职自荐信
2014/02/26 职场文书
销售人员求职的自我评价分享
2014/03/15 职场文书
2014年政务公开工作总结
2014/12/09 职场文书
汉字听写大会观后感
2015/06/12 职场文书
2016年国庆节假期旅游工作总结
2016/04/01 职场文书