3

In my Leaflet Application, on some event, I want to zoom to a particular marker, and then show it's popup. I have certain other custom components on top of the map, and the Popup that appears, is hidden behind these components.

This could be resolved, if I could zoom/pan to the map, such that the given point (i.e. location of marker) is not in the center, but slightly lower.

How do I do this?

4

This has been discussed in this Issue: https://github.com/Leaflet/Leaflet/issues/859

Based on the code given there, I wrote the following two functions:

L.Map.prototype.panToOffset = function (latlng, offset, options) {
    var x = this.latLngToContainerPoint(latlng).x - offset[0]
    var y = this.latLngToContainerPoint(latlng).y - offset[1]
    var point = this.containerPointToLatLng([x, y])
    return this.setView(point, this._zoom, { pan: options })
}

L.Map.prototype.setViewOffset = function (latlng, offset, targetZoom) {
    var targetPoint = this.project(latlng, targetZoom).subtract(offset),
    targetLatLng = this.unproject(targetPoint, targetZoom);
    return this.setView(targetLatLng, targetZoom);
}

Now these functions can be called as follows:

map.panToOffset(e.target.getLatLng(),[0,100], {"animate":true});
//or if you want to zoom to
map.setViewOffset(e.target.getLatLng(),[0,100],9);
3

You might be interested in those Leaflet plugins:

  • Leaflet-active-area: This plugin allows you to use a smaller portion of the map as an active area. All positioning methods (setView, fitBounds, setZoom) will be applied on this portion instead of the all map.
  • Leaflet.ControlledBounds: Inspired by Leaflet-active-area, automatically detects the largest area of the map not covered by any map controls and applies setView, fitBounds, setZoom, getBounds to that area.
0

The amazing answer by @Devdatta didn't directly work with me in Angular. I'm doing this based on his answer.

    // Center on Popup Open with Offset
    map.on('popupopen', (e) => {
        // Center Map with Offset
        const targetPoint = map.project(e.target._popup._latlng, e.target._zoom).subtract(MAP_POPUP_OFFSET),
            targetLatLng = map.unproject(targetPoint, e.target._zoom);
        map.setView(targetLatLng, e.target._zoom);
        // Events listeners (must use => to access "this")
        addDeviceControlEventListener(this.elementRef, this.ngZone, this.router);
    });

The MAP_POPUP_OFFSET is just

const MAP_POPUP_OFFSET = new L.Point(0, 100);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.