mobile-sdk icon indicating copy to clipboard operation
mobile-sdk copied to clipboard

Find Map Zoom by Map Bounds

Open lasyakoechlin opened this issue 3 years ago • 3 comments

Is there anyway to programmatically get (or solve for) the closest map zoom fit based on a set of MapBounds?

Basically, given a MapBounds, I want to calculate (approximate) what zoom level that corresponds to.

Thanks!

lasyakoechlin avatar Jul 17 '21 20:07 lasyakoechlin

For example, I know I can call moveToFitBounds and then when that's done I could do a getZoom on the MapView, but I want to know what Zoom level that will correspond to without having it actually move the camera.

(Basically, I am wanting to pre-calculate various zoom levels, so that based on a Map Move, I can trigger behavior based solely on the current zoom).

lasyakoechlin avatar Jul 17 '21 20:07 lasyakoechlin

@lasyakoechlin Unfortunately the answer is no. The only option is to call MapView moveToFitBounds method that updates the zoom values of the view.

mtehver avatar Jul 19 '21 08:07 mtehver

@lasyakoechlin it is very easy to compute the zoom level based on the MapBounds and map "size" Here is a JS implementation:

function getBoundsZoomLevel(bounds, mapDim, worldDim) {
    worldDim = worldDim || 256;
    const zoomMax = 22;

    function latRad(lat) {
        const sin = Math.sin((lat * Math.PI) / 180);
        const radX2 = Math.log((1 + sin) / (1 - sin)) / 2;
        return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2;
    }

    function zoom(mapPx, worldPx, fraction) {
        return Math.round(Math.log(mapPx / worldPx / fraction) / Math.LN2);
    }

    const ne = bounds.ne;
    const sw = bounds.sw;

    const latFraction = (latRad(ne.latitude) - latRad(sw.latitude)) / Math.PI;

    const lngDiff = ne.longitude - sw.longitude;
    const lngFraction = (lngDiff < 0 ? lngDiff + 360 : lngDiff) / 360;

    const latZoom = zoom(mapDim.height, worldDim, latFraction);
    const lngZoom = zoom(mapDim.width, worldDim, lngFraction);

    return Math.min(Math.min(latZoom, lngZoom), zoomMax);
}

mapDim is your mapView size and worldDim is your tileSize(256)

farfromrefug avatar Jul 19 '21 09:07 farfromrefug