Openlayers实现测量功能


Posted in Javascript onSeptember 25, 2020

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

由于公司项目需要使用到openlayers,就开始学习了openlayers,其中有一个需求需要用到测量功能,就参考《WebGisOpenlayers全面解析》写了一个小demo,话不多说,直接上代码:

<!DOCTYPE html>
<html>
 
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <title></title>
 <link rel="stylesheet" href="./ol.css" type="text/css">
 <script src="./ol.js" type="text/javascript"></script>
 <link href="https://cdn.bootcss.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet">
 <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
 <script src="https://cdn.bootcss.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
 <style type="text/css">
  #map {
   width: 100%;
   height: 100%;
   position: absolute;
  }
 
  #menu {
   float: left;
   position: absolute;
   bottom: 50px;
   right: 30px;
   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: #ffffff;
   color: black;
   border: 1px solid white;
  }
 
  .tooltip-measure:before,
  .tooltip-static:before {
   border-top: 6px solid rgba(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: #ffffff;
  }
 
  #scalebar {
   float: left;
   margin-bottom: 10px;
  }
 </style>
 
</head>
 
<body>
 <div id="map">
  <div id="menu">
   <label>测量类型选择</label>
   <select id="type">
    <option value="length">长度</option>
    <option value="area">面积</option>
   </select>
   <label class="checkbox label"><input type="checkbox" id="geodesic" />使用大地测量</label>
  </div>
 </div>
 <div id="scalebar"></div>
 <script type="text/javascript">
  $(function () {
   //格式
   var format = 'image/png';
   var bounds = [73.441277, 18.159829,
    135.08693, 53.561771];//范围
 
   //中国各省底图(面)
   var ImageMap = new ol.layer.Tile({
    source: new ol.source.TileWMS({
     ratio: 1,
     //自己的服务url
     url: 'http://localhost:8080/geoserver/China_Test/wms',
     //设置服务参数
     params: {
      'FORMAT': format,
      'VERSION': '1.1.0',
      STYLES: '',
      //图层信息
      LAYERS: 'China_Test:C_Test',
     }
    })
   });
 
   //设置地图投影
   var projection = new ol.proj.Projection({
    code: 'EPSG:4326',//投影编码
    units: 'degrees',
    axisOrientation: 'neu'
   });
 
   //设置地图 实例化一个地图
   var map = new ol.Map({
    //地图中的比例尺等控制要素
    controls: ol.control.defaults({
     attribution: false
    }).extend([
     new ol.control.FullScreen(),//全屏显示
    ]),
    //设置显示的容器
    target: 'map',
    //设置图层
    layers: [
     //添加图层
     ImageMap
    ],
    //设置视图
    view: new ol.View({
     //设置投影
     projection: projection,
     center: [102.73333, 25.05], //初始在某一点
     minZoom: 3,
     zoom: 5, //缩放级别
    }),
   });
 
   //定义矢量数据源
   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: '#e21e0a',
      width: 2
     }),
     image: new ol.style.Circle({
      radius: 5,
      fill: new ol.style.Fill({
       color: '#ffcc33'
      })
     })
    })
   });
   //将矢量图层添加到地图中
   map.addLayer(vector);
 
   //添加比例尺控件
   var scaleLineControl = new ol.control.ScaleLine({
    units: 'metric',
    target: 'scalebar',
    className: 'ol-scale-line'
   });
   map.addControl(scaleLineControl);
 
 
   //实例化鼠标位置控件
   var mousePositionControl = new ol.control.MousePosition({
    coodrdinateFormat: ol.coordinate.createStringXY(4),//坐标格式
    //地图投影坐标系
    projection: new ol.proj.Projection({
     code: 'EPSG:4326',//投影编码
     units: 'degrees',
     axisOrientation: 'neu'
    }),
    //className:'tip',
    target: document.getElementById('tip'),//显示鼠标位置信息的目标容器
    undefinedHTML: ' '//未定义坐标标记
   });
 
   //添加鼠标位置控件
   map.addControl(mousePositionControl);
 
   //实例化鹰眼控件 
   var overviewMapControl = new ol.control.OverviewMap({
    //在鹰眼中相同坐标系下不通数据源的图层
    layers: [
     new ol.layer.Tile({
      source: new ol.source.OSM({
       'url': 'http://{a-c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png'
      })
     })
    ],
    collapseLabel: '\u00BB',
    lable: '\u00AB',
    collapsed: false,
   });
   //添加鹰眼
   map.addControl(overviewMapControl);
 
   //创建一个WGS84球体对象
   var wgs84Sphere = new ol.Sphere(6378137);
   //创建一个当前要绘制的对象
   var sketch = new ol.Feature();
   //创建一个帮助提示框对象
   var helpTooltipElement;
   //创建一个帮助提示信息对象
   var helpTooltip;
   //创建一个测量提示框对象
   var measureTooltipElement;
   //创建一个测量提示信息对象
   var measureTooltip;
   //继续绘制多边形的提示信息
   var continuePolygonMsg = '单击以继续绘制多边形';
   //继续绘制线段的提示信息
   var continueLineMsg = '单击以继续绘制直线';
 
   //鼠标移动触发的函数
   var pointerMoveHandler = function (evt) {
    //Indicates if the map is currently being dragged. 
    //Only set for POINTERDRAG and POINTERMOVE events. Default is false.
    //如果是平移地图则直接结束
    if (evt.dragging) {
     return;
    }
    //帮助提示信息
    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');
   };
 
   //触发pointermove事件
   map.on('pointermove', pointerMoveHandler);
 
   //当鼠标移除地图视图的时为帮助提示要素添加隐藏样式
   $(map.getViewport()).on('mouseout', function () {
    $(helpTooltipElement).addClass('hidden');
   });
 
   //获取大地测量复选框
   var geodesicCheckbox = document.getElementById('geodesic');
   //获取类型
   var typeSelect = document.getElementById('type');
   //定义一个交互式绘图对象
   var draw;
 
   //添加交互式绘图对象的函数
   function addInteraction() {
    // 获取当前选择的绘制类型
    var type = typeSelect.value == 'area' ? 'Polygon' : 'LineString';
    //创建一个交互式绘图对象
    draw = new ol.interaction.Draw({
     //绘制的数据源
     source: source,
     //绘制类型
     type: 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;
    //定义一个控制鼠标点击次数的变量
    var count = 0;
    //绘制开始事件
    draw.on('drawstart', function (evt) {
     //The feature being drawn.
     sketch = evt.feature;
     //提示框的坐标
     var tooltipCoord = evt.coordinate;
     //监听几何要素的change事件
     //Increases the revision counter and dispatches a 'change' event.
 
     listener = sketch.getGeometry().on('change', function (evt) {
      //The event target.
      //获取绘制的几何对象
      var geom = evt.target;
      //定义一个输出对象,用于记录面积和长度
      var output;
      if (geom instanceof ol.geom.Polygon) {
       map.removeEventListener('singleclick');
       map.removeEventListener('dblclick');
       //输出多边形的面积
       output = formatArea(geom);
       //获取多变形内部点的坐标
       tooltipCoord = geom.getInteriorPoint().getCoordinates();
      } else if (geom instanceof ol.geom.LineString) {
       //输出多线段的长度
       output = formatLength(geom);
       //获取多线段的最后一个点的坐标
       tooltipCoord = geom.getLastCoordinate();
      }
 
      //设置测量提示框的内标签为最终输出结果
      measureTooltipElement.innerHTML = output;
      //设置测量提示信息的位置坐标
      measureTooltip.setPosition(tooltipCoord);
     });
 
     //地图单击事件
     map.on('singleclick', function (evt) {
      //设置测量提示信息的位置坐标,用来确定鼠标点击后测量提示框的位置
      measureTooltip.setPosition(evt.coordinate);
      //如果是第一次点击,则设置测量提示框的文本内容为起点
      if (count == 0) {
       measureTooltipElement.innerHTML = "起点";
      }
      //根据鼠标点击位置生成一个点
      var point = new ol.geom.Point(evt.coordinate);
      //将该点要素添加到矢量数据源中
      source.addFeature(new ol.Feature(point));
      //更改测量提示框的样式,使测量提示框可见
      measureTooltipElement.className = 'tooltip tooltip-static';
      //创建测量提示框
      createMeasureTooltip();
      //点击次数增加
      count++;
     });
 
     //地图双击事件
     map.on('dblclick', function (evt) {
      var point = new ol.geom.Point(evt.coordinate);
      source.addFeature(new ol.Feature(point));
     });
    }, this);
    //绘制结束事件
    draw.on('drawend', function (evt) {
     count = 0;
     //设置测量提示框的样式
     measureTooltipElement.className = 'tooltip tooltip-static';
     //设置偏移量
     measureTooltip.setOffset([0, -7]);
     //清空绘制要素
     sketch = null;
     //清空测量提示要素
     measureTooltipElement = null;
     //创建测量提示框
     createMeasureTooltip();
     //移除事件监听
     ol.Observable.unByKey(listener);
     //移除地图单击事件
     map.removeEventListener('singleclick');
    }, this);
   }
   //创建帮助提示框
   function createHelpTooltip() {
    //如果已经存在帮助提示框则移除
    if (helpTooltipElement) {
     helpTooltipElement.parentNode.removeChild(helpTooltipElement);
    }
    //创建帮助提示要素的div
    helpTooltipElement = document.createElement('div');
    //设置帮助提示要素的样式
    helpTooltipElement.className = 'tooltip hidden';
    //创建一个帮助提示的覆盖标注
    helpTooltip = new ol.Overlay({
     element: helpTooltipElement,
     offset: [15, 0],
     positioning: 'center-left'
    });
    //将帮助提示的覆盖标注添加到地图中
    map.addOverlay(helpTooltip);
   }
   //创建测量提示框
   function createMeasureTooltip() {
    //创建测量提示框的div
    measureTooltipElement = document.createElement('div');
    measureTooltipElement.setAttribute('id', 'lengthLabel');
    //设置测量提示要素的样式
    measureTooltipElement.className = 'tooltip tooltip-measure';
    //创建一个测量提示的覆盖标注
    measureTooltip = new ol.Overlay({
     element: measureTooltipElement,
     offset: [0, -15],
     positioning: 'bottom-center'
    });
    //将测量提示的覆盖标注添加到地图中
    map.addOverlay(measureTooltip);
   }
   //测量类型发生改变时触发事件
   typeSelect.onchange = function () {
    //移除之前的绘制对象
    map.removeInteraction(draw);
    //重新进行绘制
    addInteraction();
   };
 
   //格式化测量长度
   var formatLength = function (line) {
    //定义长度变量
    var length;
    //如果大地测量复选框被勾选,则计算球面距离
    if (geodesicCheckbox.checked) {
     //获取坐标串
     var coordinates = line.getCoordinates();
     //初始长度为0
     length = 0;
     //获取源数据的坐标系
     var sourceProj = map.getView().getProjection();
     //进行点的坐标转换
     for (var i = 0; i < coordinates.length - 1; i++) {
      //第一个点
      var c1 = ol.proj.transform(coordinates[i], sourceProj, 'EPSG:4326');
      //第二个点
      var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'EPSG:4326');
      //获取转换后的球面距离
      //Returns the distance from c1 to c2 using the haversine formula.
      length += wgs84Sphere.haversineDistance(c1, c2);
     }
    } else {
     //计算平面距离
     length = Math.round(line.getLength() * 100) / 100;
    }
    //定义输出变量
    var output;
    //如果长度大于1000,则使用km单位,否则使用m单位
    if (length > 1000) {
     output = (Math.round(length / 1000 * 100) / 100) + ' ' + 'km'; //换算成KM单位
    } else {
     output = (Math.round(length * 100) / 100) + ' ' + 'm'; //m为单位
    }
    return output;
   };
 
   //格式化测量面积
   var formatArea = function (polygon) {
    //定义面积变量
    var area;
    //如果大地测量复选框被勾选,则计算球面面积
    if (geodesicCheckbox.checked) {
     //获取初始坐标系
     var sourceProj = map.getView().getProjection();
     var geom = polygon.clone().transform(sourceProj, 'EPSG:4326');
     //获取多边形的坐标系
     var coordinates = geom.getLinearRing(0).getCoordinates();
     //获取球面面积
     area = Math.abs(wgs84Sphere.geodesicArea(coordinates));
    } else {
     //获取平面面积
     area = polygon.getArea();
    }
    //定义输出变量
    var output;
    //当面积大于10000时,转换为平方千米,否则为平方米
    if (area > 10000) {
     output = (Math.round(area / 1000000 * 100) / 100) + ' ' + 'km<sup>2</sup>';
    } else {
     output = (Math.round(area * 100) / 100) + ' ' + 'm<sup>2</sup>';
    }
    return output;
   };
   //添加交互绘图对象
   addInteraction();
  });
 </script>
</body>
 
</html>

效果图:

Openlayers实现测量功能

PS:这里调用的图层是使用geoserver发布的一个组合图层,可以自行定义。

源代码地址:测量实例

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

Javascript 相关文章推荐
javascript获取鼠标位置部分的实例代码(兼容IE,FF)
Aug 05 Javascript
jQuery回车实现登录简单实现
Aug 20 Javascript
jQuery控制TR显示隐藏的几种方法
Jun 18 Javascript
JavaScript DOM事件(笔记)
Apr 08 Javascript
基于Css3和JQuery实现打字机效果
Aug 11 Javascript
JavaScript数据类型学习笔记
Jan 25 Javascript
javascript判断firebug是否开启的方法
Nov 23 Javascript
Bootstrap中data-target 到底是什么
Feb 14 Javascript
Angular开发者指南之入门介绍
Mar 05 Javascript
JS关于刷新页面的相关总结
May 09 Javascript
Vue.js样式动态绑定实现小结
Jan 24 Javascript
微信小程序实现多图上传
Jun 19 Javascript
openlayers4.6.5实现距离量测和面积量测
Sep 25 #Javascript
JQuery Ajax如何实现注册检测用户名
Sep 25 #jQuery
Openlayers测量距离与面积的实现方法
Sep 25 #Javascript
基于JS实现操作成功之后自动跳转页面
Sep 25 #Javascript
OpenLayers3实现测量功能
Sep 25 #Javascript
OpenLayers3实现地图鹰眼以及地图比例尺的添加
Sep 25 #Javascript
OpenLayers3实现鼠标移动显示坐标
Sep 25 #Javascript
You might like
自己做矿石收音机
2021/03/02 无线电
Linux下PHP加速器APC的安装与配置笔记
2014/10/24 PHP
PHP中is_file()函数使用指南
2015/05/08 PHP
PHP获取用户客户端真实IP的解决方案
2016/10/10 PHP
PHP 二维关联数组根据其中一个字段排序(推荐)
2017/04/04 PHP
JS正则表达式大全(整理详细且实用)
2013/11/14 Javascript
页面元素绑定jquery toggle后元素隐藏的解决方法
2014/03/27 Javascript
轻松实现javascript图片轮播特效
2016/01/13 Javascript
基于JavaScript实现添加到购物车效果附源码下载
2016/08/22 Javascript
Node.js实现文件上传的示例
2017/06/28 Javascript
前端开发不得不知的10个最佳ES6特性
2017/08/30 Javascript
VueJS 组件参数名命名与组件属性转化问题
2018/12/03 Javascript
Vue实现按钮级权限方案
2019/11/21 Javascript
[03:06]V社市场总监Dota2项目负责人Erik专访:希望更多中国玩家加入DOTA2
2014/07/11 DOTA
python学习必备知识汇总
2017/09/08 Python
python编写分类决策树的代码
2017/12/21 Python
Python Flask基础教程示例代码
2018/02/07 Python
python GUI图形化编程wxpython的使用
2019/07/19 Python
快速解决vue.js 模板和jinja 模板冲突的问题
2019/07/26 Python
Python 仅获取响应头, 不获取实体的实例
2019/08/21 Python
pygame实现非图片按钮效果
2019/10/29 Python
python入门之井字棋小游戏
2020/03/05 Python
实现ECharts双Y轴左右刻度线一致的例子
2020/05/16 Python
vscode配置anaconda3的方法步骤
2020/08/08 Python
django使用channels实现通信的示例
2020/10/19 Python
html5 css3网站菜单实现代码
2013/12/23 HTML / CSS
阿联酋彩妆品牌:OUD MILANO
2019/10/06 全球购物
英国办公家具网站:Furniture At Work
2019/10/07 全球购物
美国在线艺术商店:HandmadePiece
2020/11/06 全球购物
教育学专业毕业生的自我鉴定
2013/11/26 职场文书
眼镜促销方案
2014/03/15 职场文书
法人代表授权委托书范文
2014/09/10 职场文书
2014国庆黄金周超市促销活动方案
2014/09/21 职场文书
2014年政风行风工作总结
2014/11/22 职场文书
2014年小学图书室工作总结
2014/12/09 职场文书
幼师自荐信范文
2015/03/06 职场文书