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之家的学习交流圈
GIS之家作品店铺:GIS之家作品店铺
GIS之家源码咨询:GIS之家webgis入门开发系列demo源代码咨询
扫码关注GIS之家微信公众号,回复“gis”可免费获取地图数据以及arcgis系列安装包等资源
GIS之家源码咨询:GIS之家webgis入门开发系列demo源代码咨询
扫码关注GIS之家微信公众号,回复“gis”可免费获取地图数据以及arcgis系列安装包等资源

浙公网安备 33010602011771号