室內(nèi)設(shè)計(jì)學(xué)校排行榜合肥正規(guī)的seo公司
vue+leaflet筆記之地圖量測
文章目錄
- vue+leaflet筆記之地圖量測
- 開發(fā)環(huán)境
- 代碼簡介
- 插件簡介與安裝
- 使用簡介
- 圖形量測
- 動(dòng)態(tài)量測
- 詳細(xì)源碼(Vue3)
本文介紹了Web端使用Leaflet
開發(fā)庫進(jìn)行距離量測的一種方法 (底圖來源:天地圖),結(jié)合leaflet-measure-path
插件能夠快速的實(shí)現(xiàn)地圖量測功能。顯示效果如下圖所示。

開發(fā)環(huán)境
Vue開發(fā)庫:3.2.37 & Leaflet開發(fā)庫:1.9.3
Leaflet主要插件:leaflet-measure-path
代碼簡介
插件簡介與安裝
leaflet-measure-path
是一個(gè)在路徑的上顯示測量結(jié)果的插件(目前支持線、面和圓圈),優(yōu)點(diǎn)是簡單易用,缺點(diǎn)是線要素的長度信息標(biāo)注在最后一個(gè)點(diǎn)的位置覺得不太合理,測量精度的話勉強(qiáng)夠用。
官方文檔 https://github.com/ProminentEdge/leaflet-measure-path
# 插件安裝
npm i leaflet-measure-path
# 插件安裝(國內(nèi)鏡像,速度較快)
npm --registry https://registry.npm.taobao.org install leaflet-measure-path
# 引入地圖量測插件 leaflet-measure-path
import 'leaflet-measure-path/leaflet-measure-path.css'
import 'leaflet-measure-path/leaflet-measure-path.js'
使用簡介
圖形量測
創(chuàng)建一些基礎(chǔ)圖形,然后利用leaflet-measure-path中的方法和屬性,對圖形進(jìn)行量測,效果如下圖所示 。

// 創(chuàng)建一個(gè)矢量面,并顯示多邊形的測量值
let polygon = L.polygon([[57.69, 11.89], [57.697, 11.88], [57.71, 11.89], [57.71, 11.91], [57.69, 11.91]], { showMeasurements: true }).addTo(map);
// 創(chuàng)建一個(gè)矢量面,當(dāng)光標(biāo)懸停在多邊形上時(shí),顯示測量值的多邊形
let polygonWithHover = L.polygon([[57.668, 11.89], [57.675, 11.88], [57.688, 11.89], [57.688, 11.91], [57.668, 11.91]], { showMeasurements: true, measurementOptions: { showOnHover: true } }).addTo(map);
// 創(chuàng)建一條折線,并顯示測量值(對測量值格式化)
L.polyline([[57.67, 11.85], [57.677, 11.86], [57.68, 11.85], [57.69, 11.86],],{showMeasurements: true, color: 'green', measurementOptions: {showTotalDistance:false,formatDistance: function valFormat(val) {// 測量值保留一位小數(shù)return '測量值:' + val.toFixed(1)}}}).addTo(map);
// 創(chuàng)建一個(gè)圓,并顯示測量值
let circle = L.circle([57.699, 11.86], {color: 'red',fillColor: '#f03',fillOpacity: 0.5,radius: 300,showMeasurements: true,
}).addTo(map);
此外,measurementOptions還提供了幾個(gè)別的屬性:
屬性 | 默認(rèn)值 | 說明 | 備注 |
---|---|---|---|
showOnHover: Boolean | false | 為true時(shí),當(dāng)用戶將光標(biāo)懸停在圖形上時(shí),測量值才會顯示 | |
showTotalDistance: Boolean | true | 為false時(shí),則不會顯示多段線的總長度 | |
minDistance: Number | 30 | 線段測量時(shí),要素中的線段必須具有的最小長度 | 實(shí)測,不生效 |
formatDistance: Function | / | 覆蓋內(nèi)置函數(shù),該函數(shù)以米為單位格式化地圖中顯示的字符串的距離 | 對顯示測量值格式化 |
formatArea: Function | / | 覆蓋內(nèi)置函數(shù),該函數(shù)將面積(平方米)格式化為地圖中顯示的字符串 | 對顯示測量值格式化 |
動(dòng)態(tài)量測
在地圖上動(dòng)態(tài)繪制線或面,進(jìn)行長度或面積的量測。

詳細(xì)源碼(Vue3)
源代碼下載地址 鏈接:https://pan.baidu.com/s/1axmOSj3cc8ve26_aODISeg?pwd=GIS6
提取碼:GIS6
<template><div class="app-contain"><!-- leaflet 地圖容器 --><div id="myMap"></div><div class="controls"><el-button color="#626aef" @click="handMeasureDistance()">距離量算</el-button><el-button color="#626aef" @click="handMeasureArea()">面積量算</el-button><el-button color="#626aef" @click="handMeasureClear()">清空</el-button></div></div>
</template><script setup>
// 引入本地標(biāo)記圖片
import deleteIconUrl from '/@/assets/images/deleteIcon.png'
// 引入樣式
import L from 'leaflet';
import 'leaflet/dist/leaflet.css'// 鼠標(biāo)提示控件
import './store/MouseTips'
import './store/MouseTips.css'
// 引入地圖量測插件 leaflet-measure-path
import 'leaflet-measure-path/leaflet-measure-path.css'
import 'leaflet-measure-path/leaflet-measure-path.js'
// 標(biāo)記點(diǎn)
let deleteIcon = L.icon({iconUrl: deleteIconUrl,iconSize: [14, 14], // 圖標(biāo)大小iconAnchor: [7, 7], // 圖標(biāo)偏移量,否則無法居住顯示
});
import { onMounted } from 'vue'
// 天地圖TK
let tdtKey = 'YOURS_TK'
// 地圖
let map = null;
// 創(chuàng)建鼠標(biāo)提示控件
let mouseTips = L.control.mouseTips({show: true,message: '鼠標(biāo)單擊左鍵加點(diǎn),雙擊結(jié)束'
});
// 距離測量方法
let distanceMeasure = {points: [],color: "red",layers: L.layerGroup(),polyline: null,polylineGroup: [],marker: null,markerGroup: [],init: function () {distanceMeasure.points = [];distanceMeasure.polyline = null;distanceMeasure.marker = null;map.on('click', distanceMeasure.click).on('dblclick', distanceMeasure.dblclick);},click: function (e) {map.doubleClickZoom.disable();// 添加點(diǎn)信息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: distanceMeasure.color });distanceMeasure.polyline.addTo(distanceMeasure.layers);distanceMeasure.layers.addTo(map);distanceMeasure.points.pop();},dblclick: function (e) { // 雙擊結(jié)束// 移除鼠標(biāo)繪制提示mouseTips.hide()distanceMeasure.polyline.addTo(distanceMeasure.layers);distanceMeasure.polylineGroup.push(distanceMeasure.polyline)map.off('click', distanceMeasure.click).off('mousemove', distanceMeasure.mousemove).off('dblclick', distanceMeasure.dblclick);},destory: function () {if (distanceMeasure.polyline) {// map.removeLayer(distanceMeasure.polyline);distanceMeasure.polylineGroup.forEach(element => {map.removeLayer(element);});}if (distanceMeasure.marker) {// distanceMeasure.marker.remove();distanceMeasure.markerGroup.forEach(element => {element.remove()})}}
}
// 面積測量方法
let areaMeasure = {points: [],color: "red",layers: L.layerGroup(),polygon: null,polygonGroup: [],marker: null,markerGroup: [],init: function () {areaMeasure.points = [];areaMeasure.polygon = null;areaMeasure.marker = null;map.on('click', areaMeasure.click).on('dblclick', areaMeasure.dblclick);},close: function (latlng) {areaMeasure.marker = L.marker(latlng, { icon: deleteIcon }).addTo(map).on("click", function (e) {if (areaMeasure.polygon)map.removeLayer(areaMeasure.polygon);if (areaMeasure.marker)areaMeasure.marker.remove();});areaMeasure.markerGroup.push(areaMeasure.marker);},click: function (e) {map.doubleClickZoom.disable();// 添加點(diǎn)信息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: areaMeasure.color });areaMeasure.polygon.addTo(areaMeasure.layers);areaMeasure.layers.addTo(map);areaMeasure.points.pop();},dblclick: function (e) { // 雙擊結(jié)束// 移除鼠標(biāo)繪制提示mouseTips.hide()areaMeasure.polygon.addTo(areaMeasure.layers);areaMeasure.polygonGroup.push(areaMeasure.polygon)areaMeasure.close(e.latlng);map.off('click', areaMeasure.click).off('mousemove', areaMeasure.mousemove).off('dblclick', areaMeasure.dblclick);},destory: function () {if (areaMeasure.polygon) {areaMeasure.polygonGroup.forEach(element => {map.removeLayer(element);});}if (areaMeasure.marker) {areaMeasure.markerGroup.forEach(element => {element.remove()})}}
}
// 地圖初始化
const initMap = () => {//影像地圖const sourceMap = L.tileLayer(`https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}`)// 注記const tiandituText = L.tileLayer(`http://t0.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${tdtKey}`)const layers = L.layerGroup([sourceMap, tiandituText])map = L.map('myMap', { //需綁定地圖容器div的idattributionControl: false,zoomControl: true, // 顯示縮放控件// 最小顯示等級minZoom: 1,// 最大顯示等級maxZoom: 18,crs: L.CRS.EPSG3857,//設(shè)置坐標(biāo)系類型 EPSG3857偽墨卡托投影scrollWheelZoom: true, //默認(rèn)開啟鼠標(biāo)滾輪縮放// 限制顯示地理范圍maxBounds: L.latLngBounds(L.latLng(-90, -180), L.latLng(90, 180)),// 限制顯示地理范圍layers: [layers] // 圖層}).setView([30, 120], 6)// 添加比例尺L.control.scale({ maxWidth: 240, metric: true, imperial: false, position: 'bottomleft' }).addTo(map);
}
// 距離量測
const handMeasureDistance = () => {// 鼠標(biāo)繪制提示mouseTips.addTo(map).show();distanceMeasure.init()
}
// 面積量測
const handMeasureArea = () => {// 鼠標(biāo)繪制提示mouseTips.addTo(map).show();areaMeasure.init()
}
// 清空量測內(nèi)容
const handMeasureClear = () => {// 鼠標(biāo)繪制提示mouseTips.addTo(map).hide();// 銷毀測量組件distanceMeasure.destory()areaMeasure.destory()
}
onMounted(() => {initMap()
})
</script><style scoped>
#myMap {width: 94vw;height: 96vh;
}.controls {position: absolute;top: 0px;left: 200px;padding: 15px;z-index: 1000;
}
</style>