Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
mongofeng opened this issue Sep 11, 2024 · 2 comments

Comments

@mongofeng
Copy link

<!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>
@fyyyyy
Copy link

fyyyyy commented Dec 13, 2024

I have the same issue with leaflet 1.9.3/ 1.9.4 and 0.2.8 of this package
Sometimes click+drag with the mouse (when the map is rotated), the map will jump to the wrong coordinates. Sometimes it works fine. I think it happens more frequently when changing zoom level.

It does NOT happen when panning with arrow keys.

SOLVED:
It had to do with the bounds, somehow the map bounds are not properly updated on rotate (sometimes). Which causes the map to jump off.

Deactivating this code "fixed" the issue for me, but its still a leaflet-rotate bug I guess

const southWest = L.latLng(-89.98155760646617, -180);
const northEast = L.latLng(89.99346179538875, 180);
const bounds = L.latLngBounds(southWest, northEast);

L.map("map", {
      // maxBounds: bounds,
      // maxBoundsViscosity: 0.9,

@mongofeng
Copy link
Author

mongofeng commented Dec 13, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants