diff --git a/src/islands/maps/GeoViewer.tsx b/src/islands/maps/GeoViewer.tsx index 48b536e..ee1fbef 100644 --- a/src/islands/maps/GeoViewer.tsx +++ b/src/islands/maps/GeoViewer.tsx @@ -19,6 +19,7 @@ export default function GeoViewer() { const mapRef = useRef(null); const mlRef = useRef(null); const fcRef = useRef(EMPTY); + const roRef = useRef(null); const [style, setStyle] = useState('auto'); const [count, setCount] = useState(0); @@ -56,9 +57,13 @@ export default function GeoViewer() { const feats = map.queryRenderedFeatures(e.point, { layers: ['geo-fill', 'geo-line', 'geo-point'] }); setSelected(feats[0]?.properties ?? null); }); + map.on('load', () => map.resize()); + const ro = new ResizeObserver(() => map.resize()); + if (containerRef.current) ro.observe(containerRef.current); + roRef.current = ro; mapRef.current = map; })(); - return () => { cancelled = true; mapRef.current?.remove(); mapRef.current = null; }; + return () => { cancelled = true; roRef.current?.disconnect(); mapRef.current?.remove(); mapRef.current = null; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); diff --git a/src/islands/maps/MapExplorer.tsx b/src/islands/maps/MapExplorer.tsx index 0d90717..5aa8d14 100644 --- a/src/islands/maps/MapExplorer.tsx +++ b/src/islands/maps/MapExplorer.tsx @@ -21,6 +21,7 @@ export default function MapExplorer() { const measureMarkersRef = useRef([]); const measureRef = useRef([]); const measuringRef = useRef(false); + const roRef = useRef(null); const [style, setStyle] = useState('auto'); const [pin, setPin] = useState(null); @@ -86,9 +87,16 @@ export default function MapExplorer() { map.addControl(new ml.GeolocateControl({ positionOptions: { enableHighAccuracy: true }, trackUserLocation: false }), 'top-right'); map.on('click', e => handleClick(e.lngLat.lat, e.lngLat.lng)); map.on('style.load', () => { ensureMeasureLayer(); refreshMeasureLine(); }); + map.on('load', () => map.resize()); + // The container is mounted via a dynamically-imported island, so it can be + // laid out after the map is created — resize once it (or its size) settles, + // otherwise the map renders blank at 0×0. + const ro = new ResizeObserver(() => map.resize()); + if (containerRef.current) ro.observe(containerRef.current); + roRef.current = ro; mapRef.current = map; })(); - return () => { cancelled = true; mapRef.current?.remove(); mapRef.current = null; }; + return () => { cancelled = true; roRef.current?.disconnect(); mapRef.current?.remove(); mapRef.current = null; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); diff --git a/src/islands/maps/StaticMap.tsx b/src/islands/maps/StaticMap.tsx index ea4bd2c..293dbc6 100644 --- a/src/islands/maps/StaticMap.tsx +++ b/src/islands/maps/StaticMap.tsx @@ -17,6 +17,7 @@ export default function StaticMap() { const mapRef = useRef(null); const mlRef = useRef(null); const markerRef = useRef(null); + const roRef = useRef(null); const [style, setStyle] = useState('auto'); const [pinCenter, setPinCenter] = useState(false); @@ -40,9 +41,13 @@ export default function StaticMap() { preserveDrawingBuffer: true, // required to read the canvas for PNG export }); map.addControl(new ml.NavigationControl(), 'top-right'); + map.on('load', () => map.resize()); + const ro = new ResizeObserver(() => map.resize()); + if (containerRef.current) ro.observe(containerRef.current); + roRef.current = ro; mapRef.current = map; })(); - return () => { cancelled = true; mapRef.current?.remove(); mapRef.current = null; }; + return () => { cancelled = true; roRef.current?.disconnect(); mapRef.current?.remove(); mapRef.current = null; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []);