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 相关文章推荐
javascript编程起步(第五课)
Feb 27 Javascript
Express作者TJ告别Node.js奔向Go
Jul 14 Javascript
jQuery实现的一个自定义Placeholder属性插件
Aug 11 Javascript
js获取元素外链样式的方法
Jan 27 Javascript
基于JS实现省市联动效果代码分享
Jun 06 Javascript
利用Angularjs实现幻灯片效果
Sep 07 Javascript
微信开发之调起摄像头、本地展示图片、上传下载图片实例
Dec 08 Javascript
html5 canvas 详细使用教程
Jan 20 Javascript
bootstrap表单按回车会自动刷新页面的解决办法
Mar 08 Javascript
vue项目刷新当前页面的三种方法
Dec 04 Javascript
js实现省级联动(数据结构优化)
Jul 17 Javascript
Element Dialog对话框的使用示例
Jul 26 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
Yii模型操作之criteria查找数据库的方法
2016/07/15 PHP
PHP数组中头部和尾部添加元素的方法(array_unshift,array_push)
2017/04/10 PHP
laravel框架路由分组,中间件,命名空间,子域名,路由前缀实例分析
2020/02/18 PHP
JavaScript事件列表解说
2006/12/22 Javascript
jQuery中文入门指南,翻译加实例,jQuery的起点教程
2007/02/09 Javascript
js 数组实现一个类似ruby的迭代器
2009/10/27 Javascript
Jquery cookie操作代码
2010/03/14 Javascript
读jQuery之四(优雅的迭代)
2011/06/20 Javascript
js 单击式的下拉菜单效果实例
2013/08/13 Javascript
当滚动条滚动到页面底部自动加载增加内容的js代码
2014/05/13 Javascript
创建、调用JavaScript对象的方法集锦
2014/12/24 Javascript
jQuery插件scroll实现无缝滚动效果
2015/04/27 Javascript
jQuery simplePage+AJAX plus分页插件用法实例
2016/02/17 Javascript
jQuery插件MovingBoxes实现左右滑动中间放大图片效果
2017/02/28 Javascript
关于Promise 异步编程的实例讲解
2017/09/01 Javascript
vue路由懒加载的实现方法
2018/03/12 Javascript
在vue2.0中引用element-ui组件库的方法
2018/06/21 Javascript
Angular6 发送手机验证码按钮倒计时效果实现方法
2019/01/08 Javascript
详解Nodejs get获取远程服务器接口数据
2019/03/26 NodeJs
用原生JS实现爱奇艺首页导航栏代码实例
2019/09/19 Javascript
关于JavaScript中异步/等待的用法与理解
2020/11/18 Javascript
Python cx_freeze打包工具处理问题思路及解决办法
2016/02/13 Python
linux下python使用sendmail发送邮件
2018/05/22 Python
利用Python将数值型特征进行离散化操作的方法
2018/11/06 Python
对python 中class与变量的使用方法详解
2019/06/26 Python
CSS3 @font-face属性使用指南
2014/12/12 HTML / CSS
美国购车网站:TrueCar
2016/10/19 全球购物
GWT的应用有哪两种部署模式
2012/12/21 面试题
单位人事专员介绍信
2014/01/11 职场文书
追悼会主持词
2014/03/20 职场文书
法制宣传标语
2014/06/23 职场文书
客户经理岗位职责
2015/01/31 职场文书
自主招生自荐信格式
2015/03/04 职场文书
先进个人自荐书
2015/03/06 职场文书
Java 语言中Object 类和System 类详解
2021/07/07 Java/Android
nginx之内存池的实现
2022/06/28 Servers