DebasishDhal99 commited on
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.

Files changed (1) hide show
  1. frontend/src/components/Map.js +84 -4
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 = ({ onMapClick }) => {
22
  useMapEvents({
23
  click(e) {
24
  const { lat, lng } = e.latlng;
25
- onMapClick(lat, lng);
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='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
242
  url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
243
  />
244
- <ClickHandler onMapClick={onMapClick}/>
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='&copy; <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