plotly / plotly.js

Open-source JavaScript charting library behind Plotly and Dash
https://plotly.com/javascript/
MIT License
16.88k stars 1.85k forks source link

Auto center/zoom for scattermapbox #3434

Open nicolaskruchten opened 5 years ago

nicolaskruchten commented 5 years ago

Right now with scattermapbox we have to manually set center and zoom but it would be great to have a flag that uses the built-in Mapbox machine to fit bounds. Something like layout.mapbox.fitbounds: true | false

https://www.mapbox.com/mapbox-gl-js/example/fitbounds/

alexcjohnson commented 5 years ago

This is equivalent to autorange for cartesian axes, so has all the same issues with figure mutation and impliedEdits. Seems to me the ideal - though this may need to happen in a major bump - would be no new attribute at all, just better defaults. So if you omit both center and zoom we automatically invoke fitbounds. Likewise if you only provide center we tell mapbox to pick a zoom that still shows all the data (but if you just changed center by panning in the GUI, zoom should not change!), and if you only provide zoom we use the same center as fitbounds would use.

nicolaskruchten commented 5 years ago

Oh to be clear, I thought this would just call the native MapBox fitBounds after rendering, and not actually write the data back to the figure :)

alexcjohnson commented 5 years ago

Of course - we can avoid pushing center and zoom back into the figure, at least with an appropriate stash of the auto results. But the impliedEdits complications will still be there... say the user zooms (either via GUI or some other interface like RCE): we'll need to explicitly clear fitbounds, then center is no longer set automatically so we'll need to explicitly pull into the figure whatever the auto center value was. All of this is much simpler if auto, rather than being an attribute in its own right, is just the absence of an explicit value, like in the histogram autobin revamp #3044.

etpinard commented 4 years ago

https://github.com/plotly/plotly.js/pull/4419 implements (or attempts to) fitbounds on geo subplot.

Mapbox subplots should be able to reuse much of the logic there.

nicolaskruchten commented 4 years ago

Awesome! Sorely needed in Mapbox-land :)

Krichardson846 commented 4 years ago

Hello! Are there any updates on this feature? This is one feature that would really save my dash app a lot of troubles!

greenafrican commented 4 years ago

Is there any update on this for mapbox subplots? I'm moving from geo to mapbox subplots and would have to manually find the zoom levels for each (over 5000) region (can get the center from d3.geoCentroid).

Is there any way to access the calculated or inferred zoom and center when fitbounds is set to locations for geo subplots?

nicolaskruchten commented 4 years ago

We’ll definitely post an update once we have one :)

I don’t have a good workaround for you at the moment either unfortunately.

jackparmer commented 4 years ago

This issue has been tagged with NEEDS SPON$OR

A community PR for this feature would certainly be welcome, but our experience is deeper features like this are difficult to complete without the Plotly maintainers leading the effort.

Sponsorship range: $10k-$15k

What Sponsorship includes:

Please include the link to this issue when contacting us to discuss.

ainar commented 3 years ago

It seems that Plotly Express already find the right level of zoom and center... How is it done?

nicolaskruchten commented 3 years ago

Plotly Express does not automatically fix the zoomlevel, and the center is just done with the centroid of the scatter points.

Note that the problem in Plotly.js is a bit more complex as a mapbox subplot can have multiple traces on it, including choropleths etc. Plotly Express has access to the entire dataset up front, and px.scatter_mapbox only makes scatter traces, so computing the centroid is much easier.

pencilcheck commented 1 year ago

Right now it seems like the best workaround is to add layout

fig.update_layout(
    autosize=True, hovermode='closest',
    mapbox = {
        'accesstoken': token,
        'center': dict(lat=40.7479944, lon=-73.9893633),
        'style': "outdoors", 'zoom': 10},
    showlegend = False)

To center and zoom in manually