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 相关文章推荐
地震发生中逃生十大法则
May 12 Javascript
jquery 弹出登录窗口实现代码
Dec 24 Javascript
JQuery 确定css方框模型(盒模型Box Model)
Jan 22 Javascript
jQuery对象和DOM对象之间相互转换的方法介绍
Feb 28 Javascript
实例剖析AngularJS框架中数据的双向绑定运用
Mar 04 Javascript
jQuery动态创建元素以及追加节点的实现方法
Oct 20 Javascript
JS根据生日月份和日期计算星座的简单实现方法
Nov 24 Javascript
node.js请求HTTPS报错:UNABLE_TO_VERIFY_LEAF_SIGNATURE\的解决方法
Dec 18 Javascript
JavaScript实现时钟滴答声效果
Jan 29 Javascript
JS开发中百度地图+城市联动实现实时触发查询地址功能
Apr 13 Javascript
详解如何在vue项目中使用eslint+prettier格式化代码
Nov 10 Javascript
JavaScript惰性载入函数实例分析
Mar 27 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
学习PHP session的传递方式
2016/06/15 PHP
PHP进行批量任务处理不超时的解决方法
2016/07/11 PHP
PHP实现负载均衡下的session共用功能
2018/04/17 PHP
php微信公众号开发之答题连闯三关
2018/10/20 PHP
解决Laravel 不能创建 migration 的问题
2019/10/09 PHP
jquery实现图片渐变切换兼容ie6/Chrome/Firefox
2013/08/02 Javascript
jquery限定文本框只能输入数字即整数和小数
2013/11/29 Javascript
document.execCommand()的用法小结
2014/01/08 Javascript
自己封装的javascript事件队列函数版
2014/06/12 Javascript
通过js为元素添加多项样式,浏览器全兼容写法
2014/08/30 Javascript
jQuery中change事件用法实例
2014/12/26 Javascript
JavaScript判断字符长度、数字、Email、电话等常用判断函数分享
2015/04/01 Javascript
JavaScript使用指针操作实现约瑟夫问题实例
2015/04/07 Javascript
js实现带有介绍的Select列表菜单实例
2015/08/18 Javascript
jquery解析json格式数据的方法(对象、字符串)
2015/11/24 Javascript
js类式继承与原型式继承详解
2016/04/07 Javascript
限制只能输入数字的实现代码
2016/05/16 Javascript
10行原生JS实现文字无缝滚动(超简单)
2018/01/02 Javascript
JavaScript格式化json和xml的方法示例
2019/01/22 Javascript
ElementUI之Message功能拓展详解
2019/10/18 Javascript
javascript+css实现进度条效果
2020/03/25 Javascript
vue-video-player实现实时视频播放方式(监控设备-rtmp流)
2020/08/10 Javascript
JavaScript 事件代理需要注意的地方
2020/09/08 Javascript
Python实现图像几何变换
2015/07/06 Python
Python中getattr函数和hasattr函数作用详解
2016/06/14 Python
Python实现点阵字体读取与转换的方法
2019/01/29 Python
Python序列对象与String类型内置方法详解
2019/10/22 Python
django 前端页面如何实现显示前N条数据
2020/03/16 Python
用 python 进行微信好友信息分析
2020/11/28 Python
HTML5页面直接调用百度地图API获取当前位置直接导航目的地的实现代码
2018/03/02 HTML / CSS
节约电力资源的建议书
2014/03/12 职场文书
职称评定自我鉴定
2014/03/18 职场文书
旅游专业毕业生自荐书
2014/06/30 职场文书
2014年文秘工作总结
2014/11/25 职场文书
python数字图像处理:图像的绘制
2022/06/28 Python
win11电脑关机鼠标灯还亮怎么解决? win11关机后鼠标灯还亮解决方法
2023/01/09 数码科技