mapbox-gl-js icon indicating copy to clipboard operation
mapbox-gl-js copied to clipboard

Zoom to bounding box (fitBounds) zooming in too far with non-Mercator projections

Open marenab opened this issue 4 years ago • 12 comments

mapbox-gl-js version: 2.6.0

browser: Chrome

Steps to Trigger Behavior

  1. Set up GL JS map using a non-Mercator projection
  2. Use fitBounds to zoom map to a defined bounding box
  3. Most apparent if the bounding box is being used ensure an entire area (e.g. admin boundary) is displayed in a window. I notice it happen more obviously if the window is small.
  4. No console errors or warnings observed.
  5. Not sure if this is related to https://github.com/mapbox/mapbox-gl-js/issues/11246 or not

Mercator (expected behavior): zoom-to-bbox-mercator

Natural Earth projection: zoom-to-bbox-naturalearth

Equal Earth projection: zoom-to-bbox-equalearth

Link to Demonstration

Made using the 'Fly To' GL JS demo: https://jsbin.com/huhataxilu/edit?html,output

Also two counties that demonstrate this issue quite clearly, reported to me:

Boulder County [-105.694362, 39.912886, -105.052774, 40.262785] Dane County [-89.838567, 42.845036, -89.008729, 43.294198]

Expected Behavior

Zoom to display the full bounding box (not cut off any area within the bounding box)

Actual Behavior

Zooms slightly too far in, cutting off part of the bounding box area. Workaround solution is to increase the padding as a 'buffer' around the bounding box.

marenab avatar Nov 15 '21 23:11 marenab

On further testing, this issue should be renamed to "Zoom bounding box (fitBounds) zooming incorrectly with non-Mercator projections.

When using 'albers' for the projection, the fitBounds does not zoom far enough in and shows much more than the bounding box. You can use the demo link above to test and just change the projection to "albers".

Similarly, when a user performs an interactive zoom (shift + draw box on desktop) the zoom function does not work as expected.

DornMoore avatar Nov 16 '21 17:11 DornMoore

Possibly related bug:

When the map is pitched with a non mercator projection, the shift+bbox zoom behaves quite erratically

screen2 https://docs.mapbox.com/mapbox-gl-js/example/map-projection/

planemad avatar Nov 30 '21 18:11 planemad

The same bug is happening with using winkelTripel projection. Zooms in way too much, like -200px is missing on each side. Default projection: image

winkelTripel projection image

csimpi avatar Mar 08 '22 00:03 csimpi

We've encountered this issue as well in some of our work. What's the primary cause of this bug? Is there a pathway to solving it?

mikelmaron avatar Jan 11 '23 15:01 mikelmaron

I had the same problem. I solved adding a center on the fitbounds method.

    let bbox = turf.bbox(currentRegion);
    map.fitBounds(bbox, {
      padding: 20,
      center: turf.center(
        turf.points([
          [bbox[0], bbox[1]],
          [bbox[2], bbox[3]]
        ])
      ).geometry.coordinates
    });

LeVarez avatar Jan 16 '23 17:01 LeVarez

I could not get adding a center to work properly. Still over-zoomed past the bounds when not using mercator. I then did a test like this...and it kind of works, but with some amusing visual results (especially if you exaggerate the duration):

    map.setProjection({
        name: 'mercator'
    });
    
    const mapPadding = 20;

    // Fit the map
    map.fitBounds(bbox, {
        padding: {top: mapPadding, bottom: mapPadding, left: mapPadding, right: mapPadding},
        duration: 5000,
        center: turf.center(
            turf.points([
                [bbox._ne.lng, bbox._ne.lat],
                [bbox._sw.lng, bbox._sw.lat]
            ])
        ).geometry.coordinates
    });

    map.setProjection({
        name: 'lambertConformalConic',
        center: [-96, 39],
        parallels: [33, 45]
    });

stonetip avatar Jan 16 '23 18:01 stonetip

@stonetip for whatever reason, adding center did work me, using albers-

chriszrc avatar Jan 25 '23 21:01 chriszrc

I could not get adding a center to work properly. Still over-zoomed past the bounds when not using mercator. I then did a test like this...and it kind of works, but with some amusing visual results (especially if you exaggerate the duration):

    map.setProjection({
        name: 'mercator'
    });
    
    const mapPadding = 20;

    // Fit the map
    map.fitBounds(bbox, {
        padding: {top: mapPadding, bottom: mapPadding, left: mapPadding, right: mapPadding},
        duration: 5000,
        center: turf.center(
            turf.points([
                [bbox._ne.lng, bbox._ne.lat],
                [bbox._sw.lng, bbox._sw.lat]
            ])
        ).geometry.coordinates
    });

    map.setProjection({
        name: 'lambertConformalConic',
        center: [-96, 39],
        parallels: [33, 45]
    });

@stonetip Oh, I noticed fitBounds does weird things if you're trying to change projection at the same time. I would put the setProjection call in a timeout so that it execute once fitBounds is done (5000ms in your example). Or alternatively, change the projection before calling fitBounds-

chriszrc avatar Feb 01 '23 15:02 chriszrc

This is still happening with the globe projection. Adding the center to the options doesn't work. Is this going to be fixed any time soon?

federico-bellucci avatar Mar 13 '24 16:03 federico-bellucci

with globe projection, fitBounds does zoom to the bounds im looking for (in my case its a collection of pins, and the top and bottom pins are at the top and bottom of the window)...but ignores the padding value. Adding a center doesnt help for me.

Dakuan avatar Mar 28 '24 08:03 Dakuan