Reputation: 2509
If I click on a marker I want to pan the map view to the center of the marker. So far this works on my project. Furthermore I want the opened popup to be aligned on the center of the map view.
I thought I could hard-code this with the leaflet-popup
class like so:
.leaflet-popup {
transform: translate(-40%, 50%) !important;
}
But this does not work. The Problem with my code is, that the popup is positioned independently of the map view. But it should be centered according to the current view. I can show you my map setup:
I provided a CodeSandBox link to play around. Click On the Marker on the top and you'll see that the popup is not aligned on the center of the screen:
const {Map, TileLayer, Marker, GeoJSON} = ReactLeaflet;
function MapOverlay({setSwipeState}) {
const mapRef = useRef(null);
const [donationLocations] = useState([
[48.135125, 11.581981], [58.403, 20.420], [43.300, 40],
[70.505, -20], [40.505, -80], [-40.505, -10]
]);
function centerMapView(e) {
const {leafletElement} = mapRef.current;
if(e) {
leafletElement.setView(e.popup._latlng); // center view to where popup opens
// todo: align popup in the middle of the screen
// Get bounds of map view, divide it by 2 and apply coorditanes to the popup position
}
}
function getMapData() {
return (
<div>
{
donationLocations.map((position, i) =>
(
<Marker position={position} key={i}>
<MarkerPopup/>
</Marker>
)
)
}
</div>
)
}
return (
<Map
ref={mapRef}
center={[45.000, 10.000]}
zoom={3}
onPopupopen={centerMapView.bind(this)}
zoomControl={false}
minZoom={3}
bounceAtZoomLimits={true}
maxBoundsViscosity={.95}
maxBounds={[[-180, -90], [180, 90]]}
>
<TileLayer
noWrap={true}
attribution='&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors | &copy <a href="https://apps.mapbox.com/feedback/">Mapbox</a>'
url={'https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=' + process.env.REACT_APP_MAPBOX_KEY}
/>
{getMapData()}
</Map>
)
}
const {Popup} = ReactLeaflet;
export default function MarkerPopup() {
return (
<Popup
autoPan={false} // Important part here
>
<Card>
...
</Card>
</Popup>
);
}
Upvotes: 4
Views: 5122
Reputation: 2509
I managed to get it working. The Solution was to make a modal dialog that is detached from the DOM.
You can see the working code: Here
// Pass open state an setOpen function from the parent
function MarkerPopup({open, setOpen}) {
const classes = useStyles();
function handleClose() {
setOpen(false);
}
return (
<Popup
autoPan={false}
>
<Modal
className={classes.modal}
open={open}
classes={{root: classes.root}}
onClose={handleClose.bind(this)}
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 0,
invisible: true
}}
>
<Card className={classes.card}>
<CardMedia
className={classes.media}
image="https://material-ui.com/static/images/cards/contemplative-reptile.jpg"
title="Contemplative Reptile"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
Lizard
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging
across all continents except Antarctica
</Typography>
</CardContent>
<CardActions>
<Button size="small" color="primary">
Details
</Button>
<Button size="small" color="primary">
Donate
</Button>
</CardActions>
</Card>
</Modal>
</Popup>
);
}
Upvotes: 4
Reputation: 17
Best solution would be to make a modal popup that is always in the center of the screen.
Display it on the event on('popupopen')
Upvotes: 0
Reputation: 3664
function centerMapView(e) {
const { leafletElement } = mapRef.current;
if (e) {
const popupLatlng = e.popup._latlng;
const zoom = leafletElement.getZoom();
const point = leafletElement.project(popupLatlng, zoom);
const newPoint = point.subtract([0, 180]);
const newLatlng = leafletElement.unproject(newPoint, zoom);
leafletElement.panTo(newLatlng, { animate: true });
}
}
You can update your centerMapView
function to the following. This will first convert your Latlng
value into a point
value, then modify the value by subtracting a specific amount of pixels ( offset ), finally converting the point
value back to Latlng
and call panTo
with the value.
Upvotes: 0