Spaces:
Runtime error
Runtime error
Commit
·
0bcfa53
1
Parent(s):
f07dae8
Simple geodistancefeature with polyline and distance text rendering
Browse files- Added key near polyline to ensure that distance key changes as the input points change. Using ToolTip for rendering the distance.
- Distance Unit options not yet present
- The polyline that joins two points are just straight lines, not proper curves.
frontend/src/components/Map.js
CHANGED
@@ -5,9 +5,12 @@ import { MapContainer, TileLayer,
|
|
5 |
useMapEvents,
|
6 |
Marker,
|
7 |
Popup ,
|
8 |
-
useMap
|
|
|
|
|
9 |
} from 'react-leaflet';
|
10 |
import L from 'leaflet';
|
|
|
11 |
import 'leaflet/dist/leaflet.css';
|
12 |
|
13 |
|
@@ -18,11 +21,11 @@ L.Icon.Default.mergeOptions({
|
|
18 |
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png',
|
19 |
});
|
20 |
|
21 |
-
const ClickHandler = ({
|
22 |
useMapEvents({
|
23 |
click(e) {
|
24 |
const { lat, lng } = e.latlng;
|
25 |
-
|
26 |
},
|
27 |
});
|
28 |
return null;
|
@@ -49,6 +52,9 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
|
|
49 |
const startWidth = useRef(0);
|
50 |
const containerRef = useRef(null);
|
51 |
|
|
|
|
|
|
|
52 |
const handleMouseDown = (e) => {
|
53 |
isDragging.current = true;
|
54 |
startX.current = e.clientX;
|
@@ -163,6 +169,37 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
|
|
163 |
setWikiWidth(20);
|
164 |
};
|
165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
return (
|
167 |
<div ref={containerRef} style={{ display: 'flex', height: '100vh', width: '100%', overflow: 'hidden' }}>
|
168 |
{panelSize !== 'closed' && (
|
@@ -241,7 +278,7 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
|
|
241 |
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
242 |
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
243 |
/>
|
244 |
-
<ClickHandler
|
245 |
<Marker position={markerPosition}>
|
246 |
{contentType === 'summary' && (
|
247 |
<Popup minWidth={250}>
|
@@ -256,6 +293,49 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
|
|
256 |
</Popup>
|
257 |
)}
|
258 |
</Marker>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
</MapContainer>
|
260 |
{panelSize === 'closed' && (
|
261 |
<button
|
|
|
5 |
useMapEvents,
|
6 |
Marker,
|
7 |
Popup ,
|
8 |
+
useMap,
|
9 |
+
Polyline,
|
10 |
+
Tooltip
|
11 |
} from 'react-leaflet';
|
12 |
import L from 'leaflet';
|
13 |
+
|
14 |
import 'leaflet/dist/leaflet.css';
|
15 |
|
16 |
|
|
|
21 |
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png',
|
22 |
});
|
23 |
|
24 |
+
const ClickHandler = ({ onClick }) => {
|
25 |
useMapEvents({
|
26 |
click(e) {
|
27 |
const { lat, lng } = e.latlng;
|
28 |
+
onClick(lat, lng);
|
29 |
},
|
30 |
});
|
31 |
return null;
|
|
|
52 |
const startWidth = useRef(0);
|
53 |
const containerRef = useRef(null);
|
54 |
|
55 |
+
const [geoPoints, setGeoPoints] = useState([]);
|
56 |
+
const [geoDistance, setGeoDistance] = useState(null);
|
57 |
+
|
58 |
const handleMouseDown = (e) => {
|
59 |
isDragging.current = true;
|
60 |
startX.current = e.clientX;
|
|
|
169 |
setWikiWidth(20);
|
170 |
};
|
171 |
|
172 |
+
const handleGeoClick = useCallback(async (lat, lon) => {
|
173 |
+
const updatedPoints = [...geoPoints, { lat, lon }];
|
174 |
+
if (updatedPoints.length > 2) {
|
175 |
+
updatedPoints.shift(); // keep only two
|
176 |
+
}
|
177 |
+
setGeoPoints(updatedPoints);
|
178 |
+
|
179 |
+
if (updatedPoints.length === 2) {
|
180 |
+
console.log("Fetching distance");
|
181 |
+
try {
|
182 |
+
|
183 |
+
const res = await fetch(`${BACKEND_URL}/geodistance`, {
|
184 |
+
method: 'POST',
|
185 |
+
headers: { 'Content-Type': 'application/json' },
|
186 |
+
body: JSON.stringify({
|
187 |
+
lat1: updatedPoints[0].lat,
|
188 |
+
lon1: updatedPoints[0].lon,
|
189 |
+
lat2: updatedPoints[1].lat,
|
190 |
+
lon2: updatedPoints[1].lon,
|
191 |
+
unit: 'km',
|
192 |
+
}),
|
193 |
+
});
|
194 |
+
const data = await res.json();
|
195 |
+
setGeoDistance(data.distance);
|
196 |
+
} catch (err) {
|
197 |
+
console.error('Failed to fetch distance:', err);
|
198 |
+
setGeoDistance(null);
|
199 |
+
}
|
200 |
+
}
|
201 |
+
}, [geoPoints]);
|
202 |
+
|
203 |
return (
|
204 |
<div ref={containerRef} style={{ display: 'flex', height: '100vh', width: '100%', overflow: 'hidden' }}>
|
205 |
{panelSize !== 'closed' && (
|
|
|
278 |
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
279 |
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
280 |
/>
|
281 |
+
<ClickHandler onClick={handleGeoClick} />
|
282 |
<Marker position={markerPosition}>
|
283 |
{contentType === 'summary' && (
|
284 |
<Popup minWidth={250}>
|
|
|
293 |
</Popup>
|
294 |
)}
|
295 |
</Marker>
|
296 |
+
|
297 |
+
{geoPoints.map((pt, index) => (
|
298 |
+
<Marker key={`geo-${index}`} position={[pt.lat, pt.lon]}>
|
299 |
+
<Popup>
|
300 |
+
Point {index + 1}: {pt.lat.toFixed(4)}, {pt.lon.toFixed(4)}
|
301 |
+
</Popup>
|
302 |
+
</Marker>
|
303 |
+
))}
|
304 |
+
|
305 |
+
{/* Polyline if 2 points are selected */}
|
306 |
+
{geoPoints.length === 2 && (
|
307 |
+
<Polyline
|
308 |
+
key={geoPoints.map(pt => `${pt.lat},${pt.lon}`).join('-')}
|
309 |
+
positions={[
|
310 |
+
[geoPoints[0].lat, geoPoints[0].lon],
|
311 |
+
[geoPoints[1].lat, geoPoints[1].lon]
|
312 |
+
]}
|
313 |
+
pathOptions={{ color: '#1976d2', weight: 4 }}
|
314 |
+
>
|
315 |
+
{geoDistance !== null && (
|
316 |
+
<Tooltip
|
317 |
+
direction="center"
|
318 |
+
permanent
|
319 |
+
offset={[0, 0]}
|
320 |
+
opacity={1}
|
321 |
+
className="distance-tooltip"
|
322 |
+
>
|
323 |
+
<span style={{
|
324 |
+
color: '#1976d2',
|
325 |
+
fontWeight: 600,
|
326 |
+
fontSize: '15px',
|
327 |
+
background: 'none',
|
328 |
+
border: 'none',
|
329 |
+
boxShadow: 'none',
|
330 |
+
padding: 0
|
331 |
+
}}>
|
332 |
+
{geoDistance.toFixed(2)} km
|
333 |
+
</span>
|
334 |
+
</Tooltip>
|
335 |
+
)}
|
336 |
+
</Polyline>
|
337 |
+
)}
|
338 |
+
|
339 |
</MapContainer>
|
340 |
{panelSize === 'closed' && (
|
341 |
<button
|