DebasishDhal99 commited on
Commit
fede4e1
·
1 Parent(s): bf630df

Add option for base, satellite view

Browse files

- Add satellite view
- Make base and satellite view selectable by user
- Add longitude lines
- Restrict maximum zoom out

Mega commit

Files changed (1) hide show
  1. frontend/src/components/Map.js +135 -6
frontend/src/components/Map.js CHANGED
@@ -8,7 +8,8 @@ import { MapContainer, TileLayer,
8
  useMap,
9
  Polyline,
10
  Tooltip,
11
- Polygon
 
12
  } from 'react-leaflet';
13
  import L from 'leaflet';
14
  import 'leaflet/dist/leaflet.css';
@@ -43,6 +44,9 @@ const ResizeHandler = ({ trigger }) => {
43
  return null;
44
  };
45
  const Map = ( { onMapClick, searchQuery, contentType } ) => {
 
 
 
46
  const [markerPosition, setMarkerPosition] = useState(null);
47
  const [wikiContent, setWikiContent] = useState(null);
48
  const [panelSize, setPanelSize] = useState('half');
@@ -52,7 +56,7 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
52
  const startX = useRef(0);
53
  const startWidth = useRef(0);
54
  const containerRef = useRef(null);
55
-
56
  const [geoPoints, setGeoPoints] = useState([]);
57
  const [geoDistance, setGeoDistance] = useState(null);
58
 
@@ -72,6 +76,8 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
72
 
73
  const [polygonPerimeter, setPolygonPerimeter] = useState(null);
74
 
 
 
75
  const handleMouseDown = (e) => {
76
  isDragging.current = true;
77
  startX.current = e.clientX;
@@ -316,6 +322,24 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
316
  const tropicOfCancerLines = generateWrappedLine(cancerLat);
317
  const tropicOfCapricornLines = generateWrappedLine(capricornLat);
318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  return (
320
  <div ref={containerRef} style={{ display: 'flex', height: '100vh', width: '100%', overflow: 'hidden' }}>
321
  {panelSize !== 'closed' && (
@@ -384,19 +408,111 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
384
  minWidth: 0,
385
  overflow: 'hidden'
386
  }}>
387
-
388
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  <MapContainer
390
  center={markerPosition || [0, 0]} // Default center if no marker position
391
  zoom={2.5} //Originally 2
392
  style={{ height: '100%', width: '100%' }}
 
 
393
  >
394
  <ResizeHandler trigger={wikiWidth} />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  <TileLayer
396
- attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
397
  url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
 
398
  />
399
-
 
400
  {/* Tropics and Equator Lines */}
401
  <>
402
  {tropicOfCancerLines.map((line, idx) => (
@@ -424,6 +540,19 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
424
  }}
425
  />
426
  ))}
 
 
 
 
 
 
 
 
 
 
 
 
 
427
  </>
428
 
429
  {/* Equator Lines */}
 
8
  useMap,
9
  Polyline,
10
  Tooltip,
11
+ Polygon,
12
+ // GeoJSON
13
  } from 'react-leaflet';
14
  import L from 'leaflet';
15
  import 'leaflet/dist/leaflet.css';
 
44
  return null;
45
  };
46
  const Map = ( { onMapClick, searchQuery, contentType } ) => {
47
+
48
+ const [baseLayer, setBaseLayer] = useState("base"); // "base" | "satellite"
49
+
50
  const [markerPosition, setMarkerPosition] = useState(null);
51
  const [wikiContent, setWikiContent] = useState(null);
52
  const [panelSize, setPanelSize] = useState('half');
 
56
  const startX = useRef(0);
57
  const startWidth = useRef(0);
58
  const containerRef = useRef(null);
59
+
60
  const [geoPoints, setGeoPoints] = useState([]);
61
  const [geoDistance, setGeoDistance] = useState(null);
62
 
 
76
 
77
  const [polygonPerimeter, setPolygonPerimeter] = useState(null);
78
 
79
+ const [viewPanelOpen, setViewPanelOpen] = useState(true);
80
+
81
  const handleMouseDown = (e) => {
82
  isDragging.current = true;
83
  startX.current = e.clientX;
 
322
  const tropicOfCancerLines = generateWrappedLine(cancerLat);
323
  const tropicOfCapricornLines = generateWrappedLine(capricornLat);
324
 
325
+ const generateLongitudeLines = (interval = 30, wraps = 1) => {
326
+ const lines = [];
327
+
328
+ for (let lon = -180; lon <= 180; lon += interval) {
329
+ for (let w = -wraps; w <= wraps; w++) {
330
+ const wrappedLon = lon + (360 * w);
331
+ lines.push([
332
+ [-90, wrappedLon],
333
+ [90, wrappedLon]
334
+ ]);
335
+ }
336
+ }
337
+
338
+ return lines;
339
+ };
340
+
341
+ // const longitudeLines = generateLongitudeLines(30, 1);
342
+
343
  return (
344
  <div ref={containerRef} style={{ display: 'flex', height: '100vh', width: '100%', overflow: 'hidden' }}>
345
  {panelSize !== 'closed' && (
 
408
  minWidth: 0,
409
  overflow: 'hidden'
410
  }}>
411
+ {/* View radio group with minimize/restore */}
412
+ {viewPanelOpen ? (
413
+ <div style={{
414
+ position: 'absolute',
415
+ top: 12,
416
+ left: 48, // moved right
417
+ zIndex: 1200,
418
+ background: 'white',
419
+ borderRadius: 8,
420
+ boxShadow: '0 2px 8px rgba(12, 12, 12, 0.08)',
421
+ padding: '6px 9px 6px 9px',
422
+ display: 'flex',
423
+ flexDirection: 'column',
424
+ gap: 0,
425
+ minWidth: 100,
426
+ transition: 'all 0.3s ease-in-out',
427
+ }}>
428
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
429
+ <span style={{ fontWeight: 600, fontSize: 16, color: '#333' }}>Map View</span>
430
+ <button
431
+ onClick={() => setViewPanelOpen(false)}
432
+ style={{
433
+ background: 'none',
434
+ border: 'none',
435
+ top: 12,
436
+ left: 48,
437
+ fontSize: 18,
438
+ cursor: 'pointer',
439
+ color: '#888',
440
+ marginLeft: 12,
441
+ lineHeight: 1,
442
+ }}
443
+ title="Minimize"
444
+ >–</button>
445
+ </div>
446
+ <label style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
447
+ <input
448
+ type="radio"
449
+ name="view"
450
+ value="base"
451
+ checked={baseLayer === "base"}
452
+ onChange={() => setBaseLayer("base")}
453
+ />
454
+ Base
455
+ </label>
456
+ <label style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
457
+ <input
458
+ type="radio"
459
+ name="view"
460
+ value="satellite"
461
+ checked={baseLayer === "satellite"}
462
+ onChange={() => setBaseLayer("satellite")}
463
+ />
464
+ Satellite
465
+ </label>
466
+ </div>
467
+ ) : (
468
+ <button
469
+ onClick={() => setViewPanelOpen(true)}
470
+ style={{
471
+ position: 'absolute',
472
+ top: 16,
473
+ left: 50,
474
+ zIndex: 1200,
475
+ background: 'white',
476
+ borderRadius: 8,
477
+ boxShadow: '0 2px 8px rgba(0,0,0,0.08)',
478
+ padding: '8px 14px',
479
+ border: '1px solid #eee',
480
+ cursor: 'pointer',
481
+ fontWeight: 600,
482
+ }}
483
+ title="Show View Options"
484
+ >
485
+ View +
486
+ </button>
487
+ )}
488
  <MapContainer
489
  center={markerPosition || [0, 0]} // Default center if no marker position
490
  zoom={2.5} //Originally 2
491
  style={{ height: '100%', width: '100%' }}
492
+ minZoom={2}
493
+ // maxZoom={5}
494
  >
495
  <ResizeHandler trigger={wikiWidth} />
496
+ {baseLayer === "satellite" && (
497
+ <>
498
+ <TileLayer
499
+ url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
500
+ attribution='&copy; <a href="https://www.esri.com/">Esri</a> & contributors'
501
+ />
502
+ <TileLayer
503
+ url="https://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png"
504
+ attribution='&copy; CartoDB'
505
+ />
506
+ </>
507
+ )}
508
+
509
+ {baseLayer === "base" && (
510
  <TileLayer
 
511
  url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
512
+ attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
513
  />
514
+ )}
515
+
516
  {/* Tropics and Equator Lines */}
517
  <>
518
  {tropicOfCancerLines.map((line, idx) => (
 
540
  }}
541
  />
542
  ))}
543
+
544
+ {generateLongitudeLines(30, 1).map((line, index) => (
545
+ <Polyline
546
+ key={`lon-line-${index}`}
547
+ positions={line}
548
+ pathOptions={{
549
+ color: '#aaa',
550
+ dashArray: '4, 4',
551
+ weight: 1,
552
+ interactive: false,
553
+ }}
554
+ />
555
+ ))}
556
  </>
557
 
558
  {/* Equator Lines */}