最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Leaflet - Align Popup on the center of the map - Stack Overflow

programmeradmin4浏览0评论

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:

EDIT

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:

Map Component

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='&amp;copy <a href="">OpenStreetMap</a> contributors | &amp;copy <a href="/">Mapbox</a>'
                url={'/{z}/{x}/{y}?access_token=' + process.env.REACT_APP_MAPBOX_KEY}
            />
            {getMapData()}
        </Map>
    )
}

Marker-Popup Component

const {Popup} = ReactLeaflet;

export default function MarkerPopup() {

    return (
        <Popup
            autoPan={false} // Important part here
        >
            <Card>
                   ...
            </Card>
        </Popup>
    );
}

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:

EDIT

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:

Map Component

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='&amp;copy <a href="http://osm/copyright">OpenStreetMap</a> contributors | &amp;copy <a href="https://apps.mapbox./feedback/">Mapbox</a>'
                url={'https://api.mapbox./styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=' + process.env.REACT_APP_MAPBOX_KEY}
            />
            {getMapData()}
        </Map>
    )
}

Marker-Popup Component

const {Popup} = ReactLeaflet;

export default function MarkerPopup() {

    return (
        <Popup
            autoPan={false} // Important part here
        >
            <Card>
                   ...
            </Card>
        </Popup>
    );
}
Share edited Nov 22, 2019 at 15:52 MarcoLe asked Nov 19, 2019 at 15:55 MarcoLeMarcoLe 2,5397 gold badges41 silver badges80 bronze badges 2
  • Hello. Is this what you have so far? If that is the case you center the marker on its y axis let's say rather than in the center of the map and the popup looks ok, centered as well. What exactly do you want to achieve? – kboul Commented Nov 22, 2019 at 8:37
  • @kboul I updated my question with a CodeSandBox link. What I want to achieve is a popup perfectly aligned on the center of the map. Greetings Marco – MarcoLe Commented Nov 22, 2019 at 11:35
Add a ment  | 

3 Answers 3

Reset to default 4

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./static/images/cards/contemplative-reptile.jpg"
                      title="Contemplative Reptile"
                  />
                  <CardContent>
                      <Typography gutterBottom variant="h5" ponent="h2">
                          Lizard
                      </Typography>
                      <Typography variant="body2" color="textSecondary" ponent="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>
  );
}
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.

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')

发布评论

评论列表(0)

  1. 暂无评论