Skip to content

When I rotate the map, the latitude and longitude returned by dragging and dropping the callback are incorrect #56

@mongofeng

Description

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

<head>
	<meta charset="UTF-8">
	<title>Leaflet Point Constrained to Line Movement</title>
	<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
		integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
		crossorigin="" />
	<style>
		#map {
			height: 500px;
		}
	</style>
</head>

<body>
	<div style="height: 500px;"></div>
	<div id="map"></div>
	<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
		integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
		crossorigin=""></script>
	<script>
		var map = L.map(mapEl.value, {
			maxZoom: 25,
			zoom: 14, //缩放比列

			minZoom: 3,
			zoomControl: false, //禁用 + - 按钮
			doubleClickZoom: false, // 禁用双击放大
			attributionControl: false, // 移除右下角leaflet标识
			zoomSnap: 1,
			rotate: true,
		}).setView([23.1799, 113.4103], 15);

		map?.setBearing(30);

		// 添加底图
		L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
			attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
		}).addTo(map);

		// 定义点列表
		var pointList = [
			{ lat: 23.17964623275198, lng: 113.41035915466436, alt: 40 },
			{ lat: 23.1802030290629, lng: 113.41031035532006, alt: 41 },
			{ lat: 23.180202162848065, lng: 113.41028334317612, alt: 42 },
			{ lat: 23.179646826779138, lng: 113.41033201465262, alt: 43 },
			{ lat: 23.179647420806287, lng: 113.41030487464066, alt: 44 },
			{ lat: 23.180201296633236, lng: 113.41025633103251, alt: 45 },
			{ lat: 23.1802004304184, lng: 113.41022931888928, alt: 46 },
			{ lat: 23.17964801483344, lng: 113.41027773462844, alt: 47 },
			{ lat: 23.179648311847014, lng: 113.41026416462223, alt: 48 },
			{ lat: 23.180199997310982, lng: 113.4102158128178, alt: 49 },
		];

		// 绘制点
		var markers = [];
		pointList.forEach(point => {
			var marker = L.marker([point.lat, point.lng])
				.addTo(map)
				.bindPopup(`Latitude: ${point.lat}, Longitude: ${point.lng}, Altitude: ${point.alt}`);
			markers.push(marker);
		});

		// 绘制线
		var polyline = L.polyline(pointList.map(point => [point.lat, point.lng]), { color: 'blue' }).addTo(map);

		// 监听线段的点击事件
		polyline.on('click', function (e) {
			var latlng = e.latlng;
			var closestSegment = getClosestSegment(latlng, pointList);

			if (closestSegment !== null) {
				var prevPoint = pointList[closestSegment.index];
				var nextPoint = pointList[closestSegment.index + 1];

				// 在相邻两个点之间添加新点
				var newPoint = getMidPoint(prevPoint, nextPoint);
				var newMarker = L.marker(newPoint)
					.addTo(map)
					.bindPopup(`New Point: Latitude: ${newPoint.lat}, Longitude: ${newPoint.lng}`)
					.on('drag', function (e) {
						var latlng = e.target.getLatLng();
						// The latitude and longitude are incorrect, and the drawing is offset
						console.log(latlng);
						e.target.setLatLng(latlng);
					})
					.on('dragend', function (e) {
						var latlng = e.target.getLatLng();
						// The latitude and longitude are incorrect, and the drawing is offset
						console.log(latlng);
					})
					.dragging.enable();
				markers.splice(closestSegment.index + 1, 0, newMarker);
				pointList.splice(closestSegment.index + 1, 0, newPoint);
				updatePolyline();
			}
		});

		// 更新折线
		function updatePolyline() {
			polyline.setLatLngs(pointList.map(point => [point.lat, point.lng]));
		}

		// 获取最近线段及其索引
		function getClosestSegment(latlng, points) {
			var minDistance = Infinity;
			var closestSegment = null;

			for (var i = 0; i < points.length - 1; i++) {
				var segmentDistance = getSegmentDistance(latlng, points[i], points[i + 1]);
				if (segmentDistance < minDistance) {
					minDistance = segmentDistance;
					closestSegment = { index: i, distance: segmentDistance };
				}
			}

			// 如果没有找到任何线段,返回 null
			return closestSegment || null;
		}

		// 计算点到线段的距离
		function getSegmentDistance(point, start, end) {
			var dx = end.lng - start.lng;
			var dy = end.lat - start.lat;
			var t = ((point.lng - start.lng) * dx + (point.lat - start.lat) * dy) / (dx * dx + dy * dy);

			// 限制 t 的范围在 0 到 1 之间
			t = Math.max(0, Math.min(1, t));

			// 计算最近点
			var closestLat = start.lat + t * dy;
			var closestLng = start.lng + t * dx;

			// 计算点到最近点的距离
			var dlat = point.lat - closestLat;
			var dlng = point.lng - closestLng;
			return Math.sqrt(dlat * dlat + dlng * dlng);
		}

		// 计算两点之间的中点
		function getMidPoint(point1, point2) {
			return L.latLng((point1.lat + point2.lat) / 2, (point1.lng + point2.lng) / 2);
		}

		// 计算直线上的最近点
		function getClosestPointOnLine(point, start, end) {
			var dx = end.lng - start.lng;
			var dy = end.lat - start.lat;
			var t = ((point.lng - start.lng) * dx + (point.lat - start.lat) * dy) / (dx * dx + dy * dy);

			// 限制 t 的范围在 0 到 1 之间
			t = Math.max(0, Math.min(1, t));

			// 计算最近点
			var closestLat = start.lat + t * dy;
			var closestLng = start.lng + t * dx;

			return L.latLng(closestLat, closestLng);
		}
	</script>
</body>

</html>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions