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 相关文章推荐
飞鱼(shqlsl) javascript作品集
Dec 16 Javascript
javascript新手语法小结
Jun 15 Javascript
javascript 二维数组的实现与应用
Mar 16 Javascript
基于JQuery实现的Select级联
Jan 27 Javascript
微信内置浏览器私有接口WeixinJSBridge介绍
May 25 Javascript
使用jquery获取url及url参数的简单实例
Jun 14 Javascript
Vue中之nextTick函数源码分析详解
Oct 17 Javascript
Echarts实现多条折线可拖拽效果
Dec 19 Javascript
vue通过v-html指令渲染的富文本无法修改样式的解决方案
May 20 Javascript
快速解决element的autofocus失效问题
Sep 08 Javascript
Vue实现返回顶部按钮实例代码
Oct 21 Javascript
uniapp微信小程序实现一个页面多个倒计时
Nov 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 SQLite类
2009/05/07 PHP
WordPress中is_singular()函数简介
2015/02/05 PHP
Zend Framework实现留言本分页功能(附demo源码下载)
2016/03/22 PHP
jquery获取ASP.NET服务器端控件dropdownlist和radiobuttonlist生成客户端HTML标签后的value和text值
2010/06/28 Javascript
jquery EasyUI的formatter格式化函数代码
2011/01/12 Javascript
Js中获取frames中的元素示例代码
2013/07/30 Javascript
Javascript实现多彩雪花从天降散落效果的方法
2015/02/02 Javascript
jQuery实现美观的多级动画效果菜单代码
2015/09/06 Javascript
Node.js 应用跑得更快 10 个技巧
2016/04/03 Javascript
Node.js实现数据推送
2016/04/14 Javascript
easyui datagrid 大数据加载效率慢,优化解决方法(推荐)
2016/11/09 Javascript
nodejs的压缩文件模块archiver用法示例
2017/01/18 NodeJs
vue2.0 axios前后端数据处理实例代码
2017/06/30 Javascript
web前端页面生成exe可执行文件的方法
2018/02/08 Javascript
vue实现点击选中,其他的不选中方法
2018/09/05 Javascript
vuex actions传递多参数的处理方法
2018/09/18 Javascript
Element ui 下拉多选时新增一个选择所有的选项
2019/08/21 Javascript
OpenLayers加载缩放控件使用方法详解
2020/09/25 Javascript
[02:30]联想杯DOTA2完美世界全国高校联赛—北京站现场
2015/11/16 DOTA
[49:59]KG vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
python cx_Oracle模块的安装和使用详细介绍
2017/02/13 Python
利用aardio给python编写图形界面
2017/08/21 Python
Python3日期与时间戳转换的几种方法详解
2019/06/04 Python
Python 3.10 的首个 PEP 诞生,内置类型 zip() 迎来新特性(推荐)
2020/07/03 Python
python 实现关联规则算法Apriori的示例
2020/09/30 Python
HTML5 CSS3给网站设计带来出色效果
2009/07/16 HTML / CSS
使用CSS禁止textarea调整大小功能的方法
2015/03/13 HTML / CSS
英国国家美术馆商店:National Gallery
2019/05/01 全球购物
日语系毕业生推荐信
2013/11/11 职场文书
接受捐赠答谢词
2014/01/27 职场文书
考核评语大全
2014/04/29 职场文书
机械工程师岗位职责
2014/06/16 职场文书
教代会开幕词
2015/01/28 职场文书
JavaScript中关于预编译、作用域链和闭包的理解
2021/03/31 Javascript
基于MySql验证的vsftpd虚拟用户
2021/11/07 MySQL
Python PIL按比例裁剪图片
2022/05/11 Python