vue(17) : leaflet(2) : 距离测量

该博客介绍了如何在Vue项目中利用Leaflet库实现地图上的测距功能。通过监听地图的点击和鼠标移动事件,动态更新测量路径和显示实时距离。使用Turf.js计算公里数,并创建自定义的提示框展示测量结果。此外,还提供了开启和关闭测距的按钮操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考 : Leaflet 简单测距_大洪的博客-优快云博客_leaflet 测距

 采用vue框架,map为leaflet的地图对象

支持重复测距

<template>
  <button @click="openDistanceCount()">开启测距</button>
  <button @click="closeDistanceCount()">关闭测距</button>
</template>

<script>
export default {
  data() {
    return {
      clickHandler: null,
      mousemoveHandler: null,
      distanceCountStart:false,
      distanceCountEnd:false,
      tempLayer:null,
      layer2:null,
      layer: null,
      popup: null
    }
  },
  created() {
  },
  methods: {
    openDistanceCount(){
      // 变量
      let tempPoints = [];
      // 自定义距离展示框
      const setTipText = content => {
        const el = document.createElement("div");
        el.className = "measure-marker";
        const text = document.createElement("span");
        text.className = "measure-text";
        text.innerHTML = content;
        const close = document.createElement("span");
        close.className = "measure-close";
        close.addEventListener("click", () => {
          remove();
        });
        el.appendChild(text);
        el.appendChild(close);
        return el;
      };
      // 移动事件
      this.mousemoveHandler = e => {
        if (tempPoints.length) {
          // 记录标记,用于计算最终距离
          tempPoints[1] = e.latlng;
          this.tempLayer.setLatLngs(tempPoints);
          // 线移动时显示距离
          this.layer2.setLatLngs(tempPoints);
          const len = turf.length(this.layer2.toGeoJSON(), { units: "kilometers" });
          this.popup
            .setLatLng(e.latlng)
            .setContent(setTipText(len.toFixed(2)*1000 + " 米"))
            .openOn(map);
        }
      };
      // 点击事件
      this.clickHandler = e => {
        if (this.distanceCountStart){
          // 测距进行中
          if (this.distanceCountEnd) {
            // 已结束,清除测量
            tempPoints = [];
            this.tempLayer.remove();
            this.layer.remove();
            this.layer2.remove();
            this.popup.remove();
            this.distanceCountStart = false
            this.distanceCountEnd = false
          } else {
            // 结束测量
            map.doubleClickZoom.enable()
            this.distanceCountEnd = true
            // 移除鼠标移动事件
            map.off("mousemove", this.mousemoveHandler);
            // 显示最终距离
            tempPoints[1] = e.latlng;
            this.layer2.setLatLngs(tempPoints);
            const len = turf.length(this.layer2.toGeoJSON(), { units: "kilometers" });
            this.popup
              .setLatLng(e.latlng)
              .setContent(setTipText(len.toFixed(2)*1000 + " 米"))
              .openOn(map);
            return null
          }
        }
        // 初始化变量
        this.distanceCountInit()
        // 执行测距
        // 绑定数据移动事件
        map.on("mousemove", this.mousemoveHandler);
        this.layer.addLatLng(e.latlng);
        tempPoints[0] = e.latlng;
        // 禁止地图拖动
        map.doubleClickZoom.disable()
        this.distanceCountStart = true
      }
      // 绑定事件
      map.on("click", this.clickHandler);
      map.on("mousemove", this.mousemoveHandler);
    },
    distanceCountInit(){
      // 测距变量初始化
      this.layer = L.polyline([], {
        interactive: false
      }).addTo(map);
      // 移到距离测量用
      this.layer2 = L.polyline([], {
        interactive: false
      });
      // 弹出展示距离信息
      this.popup = L.popup({
        autoClose: false,
        closeButton: false
      });
      // 划线
      this.tempLayer = L.polyline([], {
        interactive: false
      }).addTo(map);
    },
    closeDistanceCount(){
      // 删除线
      this.layer.remove();
      this.layer2.remove();
      this.popup.remove();
      this.tempLayer.remove();
      // 删除事件
      map.off("click", this.clickHandler);
      map.off("mousemove", this.mousemoveHandler);
    }
  },
  mounted(){
    // 引入js
    const jss = [
      'https://unpkg.com/@turf/turf@6.3.0/turf.min.js'
    ]
    jss.forEach(item=>{
      let script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = item;
      document.body.appendChild(script);
    })
  }
}
</script>

<style>
</style>

### 如何在 Leaflet 中实现测量两点间距离 要在 Leaflet 地图上实现测量两个点之间的距离,可以利用 `L.Control.Measure` 插件或其他类似的插件。下面提供一种不依赖额外插件的方法来计算并显示两点间的距离。 #### 创建地图实例 首先按照给定的方式初始化地图,在 Vue 组件中的 script 部分完成必要的导入和挂载操作[^1]: ```typescript <script lang="ts" setup> import { onMounted } from 'vue'; import "leaflet/dist/leaflet.css"; import L, { Map } from 'leaflet'; // 假设createMap函数定义如下: function createMap(): void { const map = L.map('map').setView([51.505, -0.09], 13); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); } onMounted(() => { createMap(); }) </script> ``` #### 添加标记与事件监听器 为了让用户能够点击地图选择起点和终点位置,并自动计算这两者之间直线距离(欧氏距离),可以在地图对象上绑定单击事件处理程序。每当发生一次有效的鼠标左键单击动作时就记录下坐标作为新的端点之一;当第二次单击后则触发距离计算过程并将结果显示出来。 ```javascript let startMarker; let endMarker; const calculateDistanceBetweenMarkers = () => { if (startMarker && endMarker) { let distanceInMeters = startMarker.getLatLng().distanceTo(endMarker.getLatLng()); console.log(`The straight-line distance between the two points is ${Math.round(distanceInMeters)} meters.`); // 清除之前的线段 map.eachLayer(layer => { if (layer instanceof L.Polyline) { map.removeLayer(layer); } }); // 显示连接两者的线段以及标注距离 var latlngs = [ startMarker.getLatLng(), endMarker.getLatLng() ]; L.polyline(latlngs).addTo(map); // 可选:弹窗提示距离信息 alert(`Straight line distance: ${Math.round(distanceInMeters)}m`); } }; map.on('click', function(e){ if (!startMarker) { startMarker = L.marker(e.latlng).bindPopup("Start Point").addTo(map); } else if (!endMarker) { endMarker = L.marker(e.latlng).bindPopup("End Point").addTo(map); calculateDistanceBetweenMarkers(); } else { // 如果已经有了一组完整的起始-终止对,则重置状态等待新输入 map.removeLayer(startMarker); map.removeLayer(endMarker); startMarker = null; endMarker = null; } }); ``` 这段代码实现了基本的距离测量功能,允许用户通过两次点击指定路径两端的位置,之后会立即显示出它们之间的最短地理距离,并且会在地图上绘制一条代表该路径的线条。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值