Vue工程搭建Leaflet项目第四弹:量测

7 篇文章 5 订阅
4 篇文章 0 订阅

前言

在前一篇文章已经实现了几何对象的绘制(绘制几何对象),那么接下来进行量测就比较容易实现了。具体就三个事件,一个鼠标单击事件,一个鼠标移动事件,一个双击关闭事件,通过前两个事件获取到坐标集,然后对坐标集进行操作。在leaflet中距离量测可以通过调用map对象的distance方法来实现,面积量测可以通过leaflet的量测插件或者第三方库来完成,如果是一句超图的API开发,也可以调用超图的接口实现。

地图事件应该写为方法的形式,不然关闭绘制事件的时候会关闭整个地图事件

一. 距离量测

distance(latlng1,latlng2) 通过传入两个坐标点进行量测,这里的实现思路如下
(1)当只有一个坐标点时,传入第一个坐标和鼠标移动的坐标进行计算,得到第一段动态距离,记为 d1
(2)当有两个坐标点时,传入第一个和第二个坐标点进行量算,得到第一段固定距离,记为 d2
(3)当超过两个坐标点时,传入最后两个坐标点进行量算,得到最后一段距离,记为 d3,并且与之前的距离 d2 相加得到 d4, 即 d4 = d2 + d3
(4)最后,将 d4 与动态距离 d1相加,即可得到整个路径的动态距离

measureDistance() {
  this.isMeasureDistance = !this.isMeasureDistance;
  if (window._map) {
    this.map = window._map;
    // 关闭地图双击事件
    this.map.doubleClickZoom.disable();
  }
  const latlngs = [];
  // circle 样式
  const circleOption = {
    radius: 10,
    fill: true,
    color: "yellow",
    weight: 3.5, // 边线宽度:单位像素值
    opacity: 1, // 边线透明度
    fillColor: "yellow",
    fillOpacity: 1 // 最好设置透明度,默认值0.2
  };

  // 线段样式
  const polylineOption = {
    stroke: true, // 开启路径追踪,默认为true
    color: "yellow"
  };
  // 绘制线段
  const polyline = L.polyline(latlngs, polylineOption);
  // 临时线段
  const tempLine = L.polyline([], polylineOption);
  const onClick = evt => {
    latlngs.push([evt.latlng.lat, evt.latlng.lng]);
    const circle = L.circle(evt.latlng, circleOption);
    circle.addTo(this.map);
    polyline.addLatLng(evt.latlng);
    polyline.addTo(this.map);
    if (latlngs.length === 1) {
      this.distance = this.tempDistance;
    }
    if (latlngs.length === 2) {
      this.distance = this.map.distance(latlngs[0], latlngs[1]);
    }
    if (latlngs.length > 2) {
      this.distance += this.map.distance(
        latlngs[latlngs.length - 2],
        latlngs[latlngs.length - 1]
      );
    }
  };
  this.map.on("click", onClick);
  const onMouseMove = evt => {
    // 至少有一个点才添加临时线段
    if (latlngs.length > 0) {
      // 添加临时线段
      const coords = [
        latlngs[latlngs.length - 1],
        [evt.latlng.lat, evt.latlng.lng]
      ];
      tempLine.setLatLngs(coords);
      this.map.addLayer(tempLine);
    }
    if (latlngs.length == 1) {
      this.tempDistance = this.map.distance(latlngs[0], evt.latlng);
    }
    if (latlngs.length > 1) {
      this.tempDistance = this.map.distance(
        latlngs[latlngs.length - 1],
        evt.latlng
      );
    }
  };
  this.map.on("mousemove", onMouseMove);

  // 双击结束绘制
  this.map.on("dblclick", () => {
    // 关闭单击事件
    this.map.off({ click: onClick, mousemove: onMouseMove });
    this.setCursor("pointer");
    // 开启双击事件
    this.map.doubleClickZoom.enable();
  });
},

二. 面积量测

面积量测这里我就调用第三方库 turf 来实现了(面积测量貌似有点复杂!) 直接将面的geoJSON格式传递给 turf 对象就行

注意 : turf 应以这样的方式引入 import * as turf from "@turf/turf"

measureArea() {
  this.isMeasureArea = !this.isMeasureArea;
  if (window._map) {
    this.map = window._map;
    // 关闭地图双击事件
    this.map.doubleClickZoom.disable();
  }
  const latlngs = [];
  // circle 样式
  const circleOption = {
    radius: 10,
    fill: true,
    color: "yellow",
    weight: 3.5, // 边线宽度:单位像素值
    opacity: 1, // 边线透明度
    fillColor: "yellow",
    fillOpacity: 1 // 最好设置透明度,默认值0.2
  };

  // 线段样式
  const polylineOption = {
    stroke: true, // 开启路径追踪,默认为true
    color: "yellow"
  };
  const polyline = L.polyline(latlngs, polylineOption);
  const tempLine = L.polyline([], polylineOption);
  const polygon = L.polygon(latlngs, polylineOption);
  const onClick = evt => {
    latlngs.push([evt.latlng.lat, evt.latlng.lng]);
    L.circle(evt.latlng, circleOption).addTo(this.map);
    polyline.addLatLng(evt.latlng);
    polyline.addTo(this.map);
    polygon.addLatLng(evt.latlng);
    polygon.addTo(this.map);
  };

  this.map.on("click", onClick);
  const onMouseMove = evt => {
    // 至少有一个点才添加临时线段
    if (latlngs.length > 0) {
      //面的临时线段坐标顺序[起点,鼠标移动点,最后一次点击点]
      tempLine.setLatLngs([
        latlngs[0],
        evt.latlng,
        latlngs[latlngs.length - 1]
      ]);
      //tempLine.setLatLngs([[latlngs[0],]])
      tempLine.addTo(this.map);
      polygon.setLatLngs([...latlngs, evt.latlng]);
      // 测量面积
      this.area = turf.area(polygon.toGeoJSON());
    }
  };
  this.map.on("mousemove", onMouseMove);

  this.map.on("dblclick", () => {
    // 关闭单击事件
    this.map.off({ click: onClick, mousemove: onMouseMove });
    this.setCursor("pointer");
    // 开启双击事件
    this.map.doubleClickZoom.enable();
  });
},

三、页面展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

欢迎大家关注我的公众号,我也会在公众号同步更新。

在这里插入图片描述

若大家对进阶打怪有兴趣的话,欢迎订阅以下专栏

地址:WebGIS入门和进阶实战

项目地址,请查阅

地址:leaflet-app

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值