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

Fitting map to bounds with large padding - Uncaught Error: Invalid LngLat object: (NaN, -90)

Open benstaker opened this issue 6 years ago • 5 comments

mapbox-gl-js version: v1.3.1

browser: Google Chrome (MacOS) v76.0.3809.132

Steps to Trigger Behavior

  1. Initialise the map and set the map container width and height to something small, e.g. 529px by 400px.
  2. Create a lat long bounds instance, using any number of coords
  3. Call the fitBounds method, using large padding values
  4. View the console

Link to Demonstration

https://jsfiddle.net/benstaker/thawmsjd/

Expected Behavior

Map centers to supplied bounds.

Actual Behavior

The following error outputs in the console: lng_lat.js:30 Uncaught Error: Invalid LngLat object: (NaN, -90)

benstaker avatar Sep 06 '19 09:09 benstaker

This is actually caused by an interaction between the size of the map and the padding.

We calculate the size and x and y scales necessary to fit the map to the given bounds in

https://github.com/mapbox/mapbox-gl-js/blob/75b9a4062c1f23495b1d7d10ae2c073072242920/src/ui/camera.js#L468-L470

What's causing the problem here is the scaleY calculation. The height of the map is 400 while the top and bottom paddings are 0 and 400 respectively, giving us 400 - 0 - 400 or 0.

https://github.com/mapbox/mapbox-gl-js/blob/75b9a4062c1f23495b1d7d10ae2c073072242920/src/ui/camera.js#L479

Here we calculate the necessary zoom level to fit the bounds. You can see we're taking the minimum of scaleX and scaleY, which in this case is 0 and multiplying that by tr.scale which is 256 but of course doesn't actually matter once the other side of the multiplication is set to 0.

So now we're passing 0 to tr.scaleZoom which is this:

https://github.com/mapbox/mapbox-gl-js/blob/75b9a4062c1f23495b1d7d10ae2c073072242920/src/geo/transform.js#L283

where we end up calculating Math.log(0) and MDN helpfully points out that

If the value of x is 0, the return value is always -Infinity.

From there, the rest of the calculations are borked because they're trying to operate on Infinity.

I'm not sure what the best way to handle this is to be honest. Perhaps we should catch this error and emit a warning instead.

ryanhamley avatar Sep 06 '19 20:09 ryanhamley

I just ran into this too.

There is already a check https://github.com/mapbox/mapbox-gl-js/blob/75b9a4062c1f23495b1d7d10ae2c073072242920/src/ui/camera.js#L472-L477

My opinion is that should be <= 0 since if scale is 0 you essentially need a negative infinity zoom to fit those bounds based on the canvas size and padding constraints.

There is also another edge case where scale is very small like 0.0001 then you'll need a zoom like -10 to fit, but -2 is the smallest support as far as I can tell.

In these cases, in my opinion, fitBounds should just go to the limit it can (which is a zoom of -2) plus the console warning, it won't completely meet the criteria but in these edge cases that's probably the best option.

andrewharvey avatar Jun 15 '20 03:06 andrewharvey

This bug happed to me as well, any news about solving it?

yoad-snapland avatar Jul 13 '23 10:07 yoad-snapland

This bug happed to me as well, any news about solving it?

It's not really a bug, though we need to decide and document what you can expect when making a request like this that can't be met.

At the moment you could wrap your request in a try catch, or for most cases if you're not fitting to large bounds, it's mostly sufficient to ensure you're padding is not too big compared with the map container size.

andrewharvey avatar Jul 13 '23 11:07 andrewharvey

This bug just hit me and I was clueless of why my perfectly fine data was causing the error. The error message doesn't help at all

cuginoAle avatar Oct 22 '25 09:10 cuginoAle