vue+leaflet示例:实现简单量算工具功能(附源码下载)

demo源码运行环境以及配置

  • 运行环境:依赖Node安装环境,demo本地Node版本:14.19.1。
  • 运行工具:vscode或者其他工具。
  • 配置方式:下载demo源码,vscode打开,然后顺序执行以下命令:
    (1)下载demo环境依赖包命令:npm i
    (2)启动demo命令:npm run dev
    (3)打包demo命令: npm run build:release

示例效果

本篇实现借助了一个插件leaflet-measure-path,插件的下载地址:https://github.com/ProminentEdge/leaflet-measure-path

  • 核心源码
<template>
  <div id="map" ref="mapDiv"></div>
  <div style="position: absolute; top: 50px; left: 60px; z-index: 999">
    <button type="button" id="areameasure_btn">面积量算</button>
  </div>
  <div style="position: absolute; top: 50px; left: 160px; z-index: 999">
    <button type="button" id="distanceMeasure_btn">距离量算</button>
  </div>
  <div style="position: absolute; top: 50px; left: 260px; z-index: 999">
    <button type="button" id="clear_btn">清空</button>
  </div>
  <div class="titleContainer center">
    <span>vue+leaflet示例:实现简单量算工具功能</span>
  </div>
</template>

<script setup>
import { onMounted, reactive, ref } from "vue";
import L from "leaflet";
import shanchu from "@/assets/shanchu.png";
// const mapDiv = ref(null);
let map = null;

onMounted(() => {
  // 待加载的 JS 文件数组
  const files = [
    "./lib/measure/Leaflet.Editable.js",
    "./lib/measure/leaflet-measure-path.js",
  ];
  loadScripts(files, function () {
    console.log("All scripts loaded");
    initMap();
  });
});
const loadScripts = (files, callback) => {
  if (files.length === 0) {
    callback();
    return;
  }
  const file = files.shift();
  const script = document.createElement("script");
  script.onload = function () {
    loadScripts(files, callback);
  };
  script.src = file;
  document.head.appendChild(script);
};
const initMap = () => {
  map = L.map("map");
  L.tileLayer(
    "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
    { crossOrigin: true }
  ).addTo(map);
  map.setView(L.latLng(22.95186415, 113.90271877), 14); //设置缩放级别及中心点

  //面积量算
  $("#areameasure_btn").click(function () {
    areaMeasure.destory();
    areaMeasure.init();
  });

  //距离量算
  $("#distanceMeasure_btn").click(function () {
    distanceMeasure.destory();
    distanceMeasure.init();
  });

  //清空
  $("#clear_btn").click(function () {
    distanceMeasure.destory();
    areaMeasure.destory();
  });

  const deleteIcon = L.icon({
    iconUrl: shanchu,
    iconSize: [16, 16],
  });

  // 面积测量方法
  const areaMeasure = {
    points: [],
    //markers:[],
    color: "red",
    layers: L.layerGroup(),
    polygon: null,
    marker: null,
    init: function () {
      areaMeasure.points = [];
      areaMeasure.polygon = null;
      areaMeasure.marker = null;
      map.on("click", areaMeasure.click).on("dblclick", areaMeasure.dblclick);
      L.DomUtil.addClass(map._container,'leaflet-cursor-crosshair');
    },
    close: function (latlng) {
      areaMeasure.marker = L.marker(latlng, { icon: deleteIcon })
        .addTo(map)
        .on("click", function (e) {
          //console.log('marker',e);
          if (areaMeasure.polygon) map.removeLayer(areaMeasure.polygon);

          if (areaMeasure.marker) areaMeasure.marker.remove();
        });
      //areaMeasure.markers.push(marker);
    },
    click: function (e) {
      map.doubleClickZoom.disable();
      // 添加点信息
      areaMeasure.points.push(e.latlng);
      // 添加面
      map.on("mousemove", areaMeasure.mousemove);
    },
    mousemove: function (e) {
      areaMeasure.points.push(e.latlng);
      if (areaMeasure.polygon) map.removeLayer(areaMeasure.polygon);
      areaMeasure.polygon = L.polygon(areaMeasure.points, {
        showMeasurements: true,
        color: "red",
      });
      //areaMeasure.polygon.addTo(map);
      areaMeasure.polygon.addTo(areaMeasure.layers);
      areaMeasure.layers.addTo(map);
      areaMeasure.points.pop();
    },
    dblclick: function (e) {
      // 双击结束
      console.log("双击结束", e);
      areaMeasure.polygon.addTo(areaMeasure.layers);
      areaMeasure.close(e.latlng);
      //areaMeasure.polygon.enableEdit();
      //map.on('editable:vertex:drag editable:vertex:deleted', areaMeasure.polygon.updateMeasurements, areaMeasure.polygon);
      map
        .off("click", areaMeasure.click)
        .off("mousemove", areaMeasure.mousemove)
        .off("dblclick", areaMeasure.dblclick);
      L.DomUtil.removeClass(map._container,'leaflet-cursor-crosshair');
    },
    destory: function () {
      if (areaMeasure.polygon) map.removeLayer(areaMeasure.polygon);

      if (areaMeasure.marker) areaMeasure.marker.remove();

      L.DomUtil.removeClass(map._container,'leaflet-cursor-crosshair');
    },
  };

  // 距离测量方法
  const distanceMeasure = {
    points: [],
    //markers:[],
    color: "red",
    layers: L.layerGroup(),
    polyline: null,
    marker: null,
    init: function () {
      distanceMeasure.points = [];
      distanceMeasure.polyline = null;
      distanceMeasure.marker = null;
      map
        .on("click", distanceMeasure.click)
        .on("dblclick", distanceMeasure.dblclick);

      L.DomUtil.addClass(map._container,'leaflet-cursor-crosshair');
    },
    close: function (latlng) {
      distanceMeasure.marker = L.marker(latlng, { icon: deleteIcon })
        .addTo(map)
        .on("click", function (e) {
          //console.log('marker',e);
          if (distanceMeasure.polyline)
            map.removeLayer(distanceMeasure.polyline);

          if (distanceMeasure.marker) distanceMeasure.marker.remove();
        });
    },
    click: function (e) {
      map.doubleClickZoom.disable();
      // 添加点信息
      distanceMeasure.points.push(e.latlng);
      // 添加线
      map.on("mousemove", distanceMeasure.mousemove);
    },
    mousemove: function (e) {
      distanceMeasure.points.push(e.latlng);
      if (distanceMeasure.polyline) map.removeLayer(distanceMeasure.polyline);
      distanceMeasure.polyline = L.polyline(distanceMeasure.points, {
        showMeasurements: true,
        color: "red",
      });
      distanceMeasure.polyline.addTo(distanceMeasure.layers);
      distanceMeasure.layers.addTo(map);
      distanceMeasure.points.pop();
    },
    dblclick: function (e) {
      // 双击结束
      console.log("双击结束", e);
      distanceMeasure.polyline.addTo(distanceMeasure.layers);
      distanceMeasure.close(e.latlng);
      //distanceMeasure.polygon.enableEdit();
      //map.on('editable:vertex:drag editable:vertex:deleted', distanceMeasure.polygon.updateMeasurements, distanceMeasure.polygon);
      map
        .off("click", distanceMeasure.click)
        .off("mousemove", distanceMeasure.mousemove)
        .off("dblclick", distanceMeasure.dblclick);

      L.DomUtil.removeClass(map._container,'leaflet-cursor-crosshair');
    },
    destory: function () {
      if (distanceMeasure.polyline) map.removeLayer(distanceMeasure.polyline);

      if (distanceMeasure.marker) distanceMeasure.marker.remove();

      L.DomUtil.removeClass(map._container,'leaflet-cursor-crosshair');
    },
  };
};
</script>

<style scoped>
#map {
  width: 100vw;
  height: 100vh;
}
.titleContainer {
  position: absolute;
  top: 0;
  background: rgba(0, 0, 0, 0.45);
  height: 50px;
  width: 100vw;
  z-index: 999;
  font-size: 14px;
  color: #fff;
  font-size: 28px;
}
.center {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.leaflet-cursor-crosshair {
  cursor:crosshair;
}
</style>

下载源码:GIS之家的学习交流圈

posted @ 2025-03-25 20:51  GIS之家  阅读(39)  评论(0)    收藏  举报