Leaflet使用draw实现测距、测面

源代码地址:Leaflet: https://gitee.com/SunBear/Leaflet

效果如图:

vue中安装引入leaflet组件及相关插件:

npm i leaflet

npm i leaflet-draw

// vue中引入

import * as L from "leaflet";
import "leaflet/dist/leaflet.css";

import "leaflet-draw";
import "leaflet-draw/dist/leaflet.draw.css";

完整html代码:

<!DOCTYPE html>
<html lang="en">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<link href="assets/css/map.css" rel="stylesheet">
		<link href="assets/css/leaflet.css" rel="stylesheet">
		<link href="assets/css/leaflet.draw.css" rel="stylesheet">
		<title>leaflet插件</title>
		<style>
			.map-marker-draws2{
				display: none;
			}
			.map-marker-draws {
				width: 14px !important;
				height: 14px !important;
				margin-left: -7px !important;
				margin-top: -7px !important;
				background: #3592f1;
				border: 2px solid #ffffff;
				border-radius: 100%;
			}

			.map-measure-show-area {
				color: #000;
				background: #fff;
				padding: 5px;
				font-size: 12px;
				opacity: 0.9;
				width: max-content;
			}

			.map-measure-show-length {
				color: #000;
				background: #fff;
				padding: 5px;
				font-size: 12px;
				opacity: 0.9;
				width: max-content;
			}
		</style>
	</head>

	<body>

		<div id="map"></div>
		<div class="btns" style="text-align: center;margin-top: 20px;">
			<button onclick="enableDraw('marker')">测点</button>
			<button onclick="enableDraw('polygon')">测面</button>
			<button onclick="enableDraw('polyline')">测距</button>
			<button onclick="disableDraw()">取消绘制</button>
			<button onclick="clearDraw()">清除</button>
		</div>

		<script src="assets/js/leaflet.js"></script>
		<script src="assets/js/leaflet.draw.js"></script>
		<script>
			let map = L.map("map", {
				zoom: 12,
				maxZoom: 18,
				center: [34.269701076858354, 108.94729614257814],
			});
			L.tileLayer(
				"http://{s}.tile.osm.org/{z}/{x}/{y}.png"
			).addTo(map);

			let drawLayer = null
			const layerGroup = new L.FeatureGroup().addTo(map);

			// 监听绘制完成事件
			map.on(L.Draw.Event.CREATED, (e) => {
				const {
					layer,
					layerType
				} = e;
				disableDraw(); //取消绘制、绘制初始化
				let markerLayer = null;
				layerGroup.addLayer(layer);
				if (layerType === "polygon") {
					const latlng = layer.getLatLngs()[0];
					const area = formatArea(latlng)
					markerLayer = addDivIconMarker(
						[latlng[0].lat, latlng[0].lng],
						`<div class="map-measure-show-area">面积:${area}</div>`
					);
				} else if (layerType === "polyline") {
					const latlng = layer.getLatLngs();
					const distance = formatLength(latlng);
					markerLayer = addDivIconMarker(
						[latlng[0].lat, latlng[0].lng],
						`<div class="map-measure-show-length">长度:${distance}</div>`
					);
				} else {
					const latlng = layer._latlng
					const icon = L.icon({
						iconUrl: 'assets/img/marker_icon.png',
						iconSize: [15,28],
					});
					markerLayer = L.marker([latlng.lat, latlng.lng], {
						icon: icon
					});
				}
				layerGroup.addLayer(markerLayer);
			});

			// 启动绘制
			function enableDraw(type) {
				if (drawLayer) return; //防止重复绘制
				let config = {
					drawLocal: {
						marker: {
							tooltip: {
								start: "单击放置标记,按esc退出",
							},
						},
						polyline: {
							tooltip: {
								start: "点击地图开始画线",
								cont: "继续选择",
								end: "双击完成绘制",
							},
						},
						polygon: {
							error: "<strong>错误:</strong>无法形成面 请重新绘制",
							tooltip: {
								start: "点击地图开始绘制多边形",
								cont: "继续选择",
								end: "双击或者点击第一个顶点完成绘制",
							},
						},
					},
					drawConfig: {
						marker: {
							icon: L.divIcon({
								className: "map-marker-draws2",
							}),
							shapeOptions: {
								color: "#3592f1",
							},
						},
						polyline: {
							icon: L.divIcon({
								className: "map-marker-draws",
							}),
							shapeOptions: {
								color: "#3592f1",
							},
						},
						polygon: {
							icon: L.divIcon({
								className: "map-marker-draws",
							}),
							shapeOptions: {
								color: "#3592f1",
							},
						},
					},
				};
				if (type === "marker") {
					L.drawLocal.draw.handlers.marker =
						config.drawLocal.marker;
					drawLayer = new L.Draw.Marker(
						map,
						config.drawConfig.marker
					);
				} else if (type === "polyline") {
					L.drawLocal.draw.handlers.polyline =
						config.drawLocal.polyline;
					drawLayer = new L.Draw.Polyline(
						map,
						config.drawConfig.polyline
					);
				} else {
					L.drawLocal.draw.handlers.polygon =
						config.drawLocal.polygon;
					drawLayer = new L.Draw.Polygon(
						map,
						config.drawConfig.polygon
					);
				}
				drawLayer.enable(); // 启动绘制
			}

			// 取消绘制
			function disableDraw() {
				if (drawLayer) {
					drawLayer.disable();
					drawLayer = null;
				}
			}
			// 清除绘制
			function clearDraw() {
				layerGroup.clearLayers();
			}
			/**
			 * 添加自定义div标注
			 * @param {*} coordinate 坐标
			 * @param {*} divHtml htm字符串
			 * @param {*} option 配置项
			 * @returns
			 */
			function addDivIconMarker(
				coordinate = [],
				divHtml,
				option = {}
			) {
				const divIcon = L.divIcon({
					className: "hidden-icon",
					html: divHtml,
					...option,
				});
				const marker = L.marker(coordinate, {
					icon: divIcon,
				});
				return marker;
			}

			// 测面
			function formatArea(coordinate = []) {
				const seeArea = L.GeometryUtil.geodesicArea(coordinate); //单位默认平方米
				return seeArea.toFixed(2) + 'm²';
			}

			// 测距
			function formatLength(coordinate = []) {
				let dis = 0;
				for (let i = 0; i < coordinate.length - 1; i++) {
					let start = coordinate[i];
					let end = coordinate[i + 1];
					dis += L.latLng([start.lat, start.lng]).distanceTo([end.lat, end.lng]);
				}
				if (dis > 1000) {
					return (dis / 10e2).toFixed(2) + 'km'
				} else {
					return dis.toFixed(2) + 'm';
				}
			}
		</script>
	</body>

</html>

相关api参考:

GitHub - Leaflet/Leaflet.draw: Vector drawing and editing plugin for Leaflet

Leaflet Draw Documentation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值