I have some dynamic data inside <Popup>
that will change the Popup box size after opening. When you first click on the <Marker>
it will update the content, position and adjust the pan of your map to fit direct at the top of Popup box.
However if the data (in this case an img) inside the Popup box changes it, your view wont move and will be cut off:
This is what I want to happen when updating data inside the Popup box. It adjusts your view to the very top of the popup box:
I've tried a few things like setting autopan autoPan={true}
or manually updating view on click:
const onClickHandler = () => {
const currentCenter = map.getCenter();
const mapZoom = map.getZoom();
const newCenter = [currentCenter.lat + (5 / mapZoom), currentCenter.lng];
map.flyTo(newCenter, mapZoom);
}
but it doesn't really work as well as clicking open <Marker>
. Are there any hooks that I'm missing that is able to update the Popup when the size changes?
import React, { useEffect, useState, useRef } from 'react'
import { MapContainer, TileLayer, Popup, LayersControl, Marker, useMap, useMapEvents } from 'react-leaflet';
const MyMap = () => {
const [showImage, setShowImage] = useState(false);
const handleButtonClick = () => setShowImage(!showImage);
const position = [51.805, -0.11];
const popupRef = useRef(null);
return (
<MapContainer center={position} zoom={3} minZoom={2} scrollWheelZoom={true} style={{ height: "100vh", width: "100%" }}>
<TileLayer
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={position}>
<Popup minWidth={200}>
{showImage &&
<img style={{maxWidth: "500px"}} src="https://upload.wikimedia.org/wikipedia/commons/9/9b/Photo_of_a_kitten.jpg" alt="cat" />
}
<button onClick={handleButtonClick} style={{width: "100px", height: "150px"}}>
Click me!
</button>
</Popup>
</Marker>
</MapContainer>
)
}
export default MyMap;
You could define a new state autopan
which is false
initially, but gets set to true
when clicking the button to show the image, and back to false
immediately after the image state is uodated:
const [autopan, setAutopan] = useState(false);
const handleButtonClick = () => {
setAutopan(true)
setShowImage(!showImage)
setAutopan(false)
};
Then wire the keepInView attribute of the <Popup>
up to this new autopan
state:
<Popup minWidth={200} keepInView={autopan}>
...
</Popup>
This now means that after clicking the button to show the image, the map will pan to the top of the popup, and resetting it back to false after will allow the user to move the map so that the popup is off screen if they wish.
Here's a StackBlitz that demonstrates this working.