import { useEffect, useRef, useState } from 'react'; import { useMap, Polyline, Marker } from 'react-leaflet'; import L from 'leaflet'; interface MeasurementToolProps { enabled: boolean; onComplete?: (distanceKm: number) => void; } function haversineKm( lat1: number, lon1: number, lat2: number, lon2: number ): number { const R = 6371; const dLat = ((lat2 - lat1) * Math.PI) / 180; const dLon = ((lon2 - lon1) * Math.PI) / 180; const a = Math.sin(dLat / 2) ** 2 + Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) * Math.sin(dLon / 2) ** 2; return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); } function totalDistance(pts: [number, number][]): number { let total = 0; for (let i = 1; i < pts.length; i++) { total += haversineKm(pts[i - 1][0], pts[i - 1][1], pts[i][0], pts[i][1]); } return total; } const dotIcon = L.divIcon({ className: '', iconSize: [10, 10], iconAnchor: [5, 5], html: '
', }); export default function MeasurementTool({ enabled, onComplete }: MeasurementToolProps) { const map = useMap(); const [points, setPoints] = useState<[number, number][]>([]); const pointsRef = useRef(points); pointsRef.current = points; // Clear on disable useEffect(() => { if (!enabled) { setPoints([]); } }, [enabled]); // Click handler: add measurement point useEffect(() => { if (!enabled) return; const handleClick = (e: L.LeafletMouseEvent) => { setPoints((prev) => [...prev, [e.latlng.lat, e.latlng.lng]]); }; const handleRightClick = (e: L.LeafletMouseEvent) => { L.DomEvent.preventDefault(e.originalEvent); const pts = pointsRef.current; if (pts.length >= 2 && onComplete) { onComplete(totalDistance(pts)); } setPoints([]); }; map.on('click', handleClick); map.on('contextmenu', handleRightClick); return () => { map.off('click', handleClick); map.off('contextmenu', handleRightClick); }; }, [map, enabled, onComplete]); if (!enabled || points.length === 0) return null; const dist = totalDistance(points); return ( <> {points.length >= 2 && ( )} {points.map((pos, idx) => ( ))} {dist > 0 && (
Distance: {dist.toFixed(2)} km ({(dist * 1000).toFixed(0)} m)
)} ); }