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 相关文章推荐
input 和 textarea 输入框最大文字限制的jquery插件
Oct 27 Javascript
基于jQuery的计算文本框字数的代码
Jun 06 Javascript
jquery原创弹出层折叠效果点击折叠弹出一个层
Mar 12 Javascript
node.js学习总结之调式代码的方法
Jun 25 Javascript
JS实现文字放大效果的方法
Mar 03 Javascript
深入学习JavaScript中的Rest参数和参数默认值
Jul 28 Javascript
原生js图片轮播效果实现代码
Oct 19 Javascript
用JavaScript实现让浏览器停止载入页面的方法
Jan 19 Javascript
angular2中使用第三方js库的实例
Feb 26 Javascript
Typescript的三种运行方式(小结)
Sep 18 Javascript
vuex管理状态仓库使用详解
Jul 29 Javascript
全局安装 Vue cli3 和 继续使用 Vue-cli2.x操作
Sep 08 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
PHP4.04简明安装
2006/10/09 PHP
PHP strtotime函数详解
2009/12/18 PHP
php简单开启gzip压缩方法(zlib.output_compression)
2013/04/13 PHP
ThinkPHP V2.2说明文档没有说明的那些事实例小结
2015/07/01 PHP
学习php设计模式 php实现原型模式(prototype)
2015/12/07 PHP
Mootools 1.2教程(3) 数组使用简介
2009/09/14 Javascript
functional继承模式 摘自javascript:the good parts
2011/06/20 Javascript
jquery利用event.which方法获取键盘输入值的代码
2011/10/09 Javascript
formvalidator验证插件中有关ajax验证问题
2013/01/04 Javascript
js获取当月最后一天实例代码
2013/11/19 Javascript
几种设置表单元素中文本输入框不可编辑的方法总结
2013/11/25 Javascript
JS实现仿百度输入框自动匹配功能的示例代码
2014/02/19 Javascript
Javascript基础教程之数据类型 (数值 Number)
2015/01/18 Javascript
Bootstrap自动适应PC、平板、手机的Bootstrap栅格系统
2016/05/27 Javascript
深入理解requestAnimationFrame的动画循环
2016/09/20 Javascript
JavaScript模板引擎Template.js使用详解
2016/12/15 Javascript
js实现点击切换checkbox背景图片的简单实例
2017/05/08 Javascript
详解基于Vue2.0实现的移动端弹窗(Alert, Confirm, Toast)组件
2018/08/02 Javascript
vue-cli设置publicPath小记
2020/04/14 Javascript
python实现超简单端口转发的方法
2015/03/13 Python
Python单链表简单实现代码
2016/04/27 Python
python模拟登录并且保持cookie的方法详解
2017/04/04 Python
Python3.4实现远程控制电脑开关机
2018/02/22 Python
python实现手机销售管理系统
2019/03/19 Python
django celery redis使用具体实践
2019/04/08 Python
Python使用urllib模块对URL网址中的中文编码与解码实例详解
2020/02/18 Python
在Python 的线程中运行协程的方法
2020/02/24 Python
巴西男士胡须和头发护理产品商店:Beard
2017/11/13 全球购物
实习生的自我鉴定范文欣赏
2013/11/20 职场文书
银行员工职业规划范文
2014/01/21 职场文书
信息管理与信息系统专业求职信
2014/06/21 职场文书
会计专业毕业生求职信
2014/07/04 职场文书
公共机构节能宣传周活动总结
2014/07/09 职场文书
门店店长岗位职责
2015/04/14 职场文书
中秋节英文祝福语句(14句)
2019/09/11 职场文书
Nginx隐藏式跳转(浏览器URL跳转后保持不变)
2022/04/07 Servers