Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/components/CoordinatesDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ export function CoordinatesDisplay({
mapRef,
externalSearchRef,
externalSearchMarkerRef,
isMapInitialized,
}: {
flipped: boolean;
mapRef: React.RefObject<Map | null>;
externalSearchRef: React.RefObject<HTMLDivElement | null>;
externalSearchMarkerRef: React.RefObject<Feature<Geometry> | null>;
isMapInitialized: boolean;
}) {
const [coordinates, setCoordinates] = useState<number[] | undefined>(
undefined
Expand Down Expand Up @@ -56,12 +58,12 @@ export function CoordinatesDisplay({
}, []);

useEffect(() => {
if (!mapRef.current) return;
if (!mapRef.current || !isMapInitialized) return;
const currentMapRef = mapRef.current;
const updateCoords = (e: MapBrowserEvent) => setCoordinates(e.coordinate);
currentMapRef.on('pointermove', updateCoords);
return () => currentMapRef.un('pointermove', updateCoords);
}, [mapRef]);
}, [mapRef, isMapInitialized]);

const onSubmit = useCallback(
(e: FormEvent) => {
Expand Down
10 changes: 9 additions & 1 deletion src/components/OpenLayersMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export function OpenLayersMap({
const [isDrawing, setIsDrawing] = useState(false);
const [isNewBoxDrawn, setIsNewBoxDrawn] = useState(false);
const [flipTiles, setFlipTiles] = useState(true);
const [isMapInitialized, setIsMapInitialized] = useState(false);

const [backHistoryStack, setBackHistoryStack] = useState<
{ id: string; flipped: boolean }[]
Expand Down Expand Up @@ -277,6 +278,8 @@ export function OpenLayersMap({
view: new View(DEFAULT_INTERNAL_MAP_SETTINGS),
});

setIsMapInitialized(true);

/**
* BEGIN
* Set up overlay, markers, and events for the external searches functionality
Expand Down Expand Up @@ -570,12 +573,17 @@ export function OpenLayersMap({
goBack={goBack}
goForward={goForward}
/>
<GraticuleLayer mapRef={mapRef} flipped={flipTiles} />
<GraticuleLayer
mapRef={mapRef}
flipped={flipTiles}
isMapInitialized={isMapInitialized}
/>
<CoordinatesDisplay
flipped={flipTiles}
mapRef={mapRef}
externalSearchRef={externalSearchRef}
externalSearchMarkerRef={externalSearchMarkerRef}
isMapInitialized={isMapInitialized}
/>
</div>
);
Expand Down
123 changes: 61 additions & 62 deletions src/components/layers/GraticuleLayer.tsx
Original file line number Diff line number Diff line change
@@ -1,83 +1,82 @@
import { useCallback, useEffect } from 'react';
import { useEffect, useRef } from 'react';
import { Graticule, Map } from 'ol';
import Stroke from 'ol/style/Stroke';
import { NUMBER_OF_FIXED_GRATICULE_DECIMALS } from '../../configs/mapSettings';

export function GraticuleLayer({
mapRef,
flipped,
isMapInitialized,
}: {
mapRef: React.RefObject<Map | null>;
flipped: boolean;
isMapInitialized: boolean;
}) {
const handleLatLabelFormat = useCallback((lat: number) => {
if (Number.isInteger(lat) || String(lat).length < 5) {
return String(lat);
}
const gratRef = useRef<Graticule[] | null>(null);

const formatLat = (lat: number) => {
if (Number.isInteger(lat) || String(lat).length < 5) return String(lat);
return String(lat.toFixed(NUMBER_OF_FIXED_GRATICULE_DECIMALS));
}, []);
};

const handleLonLabelFormat = useCallback(
(lon: number) => {
if (Number.isInteger(lon) || String(lon).length < 5) {
return String(flipped ? lon * -1 + 180 : lon);
}
return String(
(flipped ? lon * -1 + 180 : lon).toFixed(
NUMBER_OF_FIXED_GRATICULE_DECIMALS
)
);
},
[flipped]
);
const formatLon = (lon: number) => {
const fixed = flipped ? lon * -1 + 180 : lon;
if (Number.isInteger(fixed) || String(fixed).length < 5)
return String(fixed);
return String(fixed.toFixed(NUMBER_OF_FIXED_GRATICULE_DECIMALS));
};

useEffect(() => {
if (mapRef.current) {
mapRef.current.getAllLayers().forEach((l) => {
const id = l.getProperties().id;
if (id && id.includes('graticule-')) {
mapRef.current?.removeLayer(l);
}
});
const map = mapRef.current;
if (!map || !isMapInitialized) return;

const graticule1 = new Graticule({
strokeStyle: new Stroke({
color: 'rgba(198,198,198,0.5)',
width: 2,
}),
zIndex: 1000,
showLabels: true,
lonLabelPosition: 0,
latLabelPosition: 0.999,
latLabelFormatter: handleLatLabelFormat,
lonLabelFormatter: handleLonLabelFormat,
wrapX: false,
properties: {
id: 'graticule-1',
},
});
// Remove old graticule layers
if (gratRef.current) {
gratRef.current.forEach((g) => map.removeLayer(g));
gratRef.current = null;
}

const graticule2 = new Graticule({
strokeStyle: new Stroke({
color: 'rgba(198,198,198,0.5)',
width: 2,
}),
zIndex: 1000,
showLabels: true,
lonLabelPosition: 1,
latLabelPosition: 0.035,
latLabelFormatter: handleLatLabelFormat,
lonLabelFormatter: handleLonLabelFormat,
wrapX: false,
properties: {
id: 'graticule-2',
},
});
const stroke = new Stroke({
color: 'rgba(198,198,198,0.5)',
width: 2,
});

mapRef.current.addLayer(graticule1);
mapRef.current.addLayer(graticule2);
}
}, [mapRef, flipped, handleLatLabelFormat, handleLonLabelFormat]);
const g1 = new Graticule({
strokeStyle: stroke,
zIndex: 1000,
showLabels: true,
lonLabelPosition: 0,
latLabelPosition: 0.999,
latLabelFormatter: formatLat,
lonLabelFormatter: formatLon,
wrapX: false,
properties: { id: 'graticule-1' },
});

const g2 = new Graticule({
strokeStyle: stroke,
zIndex: 1000,
showLabels: true,
lonLabelPosition: 1,
latLabelPosition: 0.035,
latLabelFormatter: formatLat,
lonLabelFormatter: formatLon,
wrapX: false,
properties: { id: 'graticule-2' },
});

gratRef.current = [g1, g2];

map.addLayer(g1);
map.addLayer(g2);

// Cleanup on unmount
return () => {
if (!map || !gratRef.current) return;
gratRef.current.forEach((g) => map.removeLayer(g));
gratRef.current = null;
};
}, [mapRef, flipped, isMapInitialized]);

return null;
}