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 相关文章推荐
麦鸡的TAB切换功能结合了javascript和css
Dec 17 Javascript
为JavaScript提供睡眠功能(sleep) 自编译JS引擎
Aug 16 Javascript
js带前后翻页的图片切换效果代码分享
Sep 08 Javascript
JS组件Bootstrap Table表格行拖拽效果实现代码
Aug 27 Javascript
JS命令模式例子之菜单程序
Oct 10 Javascript
理解JavaScript原型链
Oct 25 Javascript
JS按钮闪烁功能的实现代码
Jul 21 Javascript
在vue项目创建的后初始化首次使用stylus安装方法分享
Jan 25 Javascript
vue iview组件表格 render函数的使用方法详解
Mar 15 Javascript
详解用场景去理解函数柯里化(入门篇)
Apr 11 Javascript
详解nginx配置vue h5 history去除#号
Nov 09 Javascript
React 并发功能体验(前端的并发模式)
Jul 01 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 模拟登陆MSN并获得用户信息
2009/05/16 PHP
php中instanceof 与 is_a()区别分析
2015/03/03 PHP
PHP中的数组处理函数实例总结
2016/01/09 PHP
php文档工具PHP Documentor安装与使用方法
2016/01/25 PHP
PHP二维数组实现去除重复项的方法【保留各个键值】
2017/12/21 PHP
ThinkPHP框架实现FTP图片上传功能示例
2019/04/08 PHP
用JavaScript获取网页中的js、css、Flash等文件
2006/12/20 Javascript
ModelDialog JavaScript模态对话框类代码
2011/04/17 Javascript
jquery动画1.加载指示器
2012/08/24 Javascript
使用js写的一个简易的投票
2013/11/27 Javascript
JQuery中使用ajax传输超大数据的解决方法
2014/07/14 Javascript
Javascript中prototype属性实现给内置对象添加新的方法
2015/05/14 Javascript
基于Jquery easyui 选中特定的tab
2015/11/17 Javascript
ES6 对象的新功能与解构赋值介绍
2019/02/05 Javascript
利用Vconsole和Fillder进行移动端抓包调试方法
2019/03/05 Javascript
vue路由--网站导航功能详解
2019/03/29 Javascript
微信小程序select下拉框实现效果
2019/05/15 Javascript
[33:23]VG vs Pain 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
python查询sqlite数据表的方法
2015/05/08 Python
python: 判断tuple、list、dict是否为空的方法
2018/10/22 Python
python3实现elasticsearch批量更新数据
2019/12/03 Python
python+Selenium自动化测试——输入,点击操作
2020/03/06 Python
完美解决ARIMA模型中plot_acf画不出图的问题
2020/06/04 Python
解决python 执行sql语句时所传参数含有单引号的问题
2020/06/06 Python
Django通过设置CORS解决跨域问题
2020/11/26 Python
html5小程序飞入购物车(抛物线绘制运动轨迹点)
2020/10/19 HTML / CSS
QA工程师岗位职责
2013/11/20 职场文书
工程招投标邀请书
2014/01/30 职场文书
《维生素c的故事》教学反思
2014/02/18 职场文书
家长学校培训材料
2014/08/20 职场文书
2015年教育实习工作总结
2015/04/24 职场文书
2015年工会工作总结范文
2015/07/23 职场文书
三八妇女节致辞
2015/07/31 职场文书
JS中一些高效的魔法运算符总结
2021/05/06 Javascript
Django显示可视化图表的实践
2021/05/10 Python
详解Oracle数据库中自带的所有表结构(sql代码)
2021/11/20 Oracle