Reputation: 205
I currently have a simple Dash app with a plotly
choropleth map figure inside. The base code looks like this:
# imports
import core # helper package
import numpy as np
import plotly.graph_objects as go
from dash import Dash, html, dcc, Input, Output
# create app
app = Dash(__name__)
# get data
df = core.find.data()
counties = core.get.counties()
# create main figure
fig = go.Figure(go.Choroplethmapbox(
geojson=counties,
locations=df.fips,
z=df.data,
zmin=0, zmax=0.5,
))
fig.update_layout(
mapbox_style='open-street-map',
mapbox_zoom=3,
mapbox_center={'lat': 37.0902, 'lon': -95.7129},
)
fig.update_layout(
margin={ 'r': 0, 't': 0, 'l': 0, 'b': 0 }
)
# create app layout
app.layout = html.Div(children=[
dcc.Graph(
id='graph',
figure=fig
),
])
# run app
if __name__ == '__main__':
app.run_server(debug=True)
At this point, everything is working fine. However, I recently added a dropdown that was intended to automatically switch the view of the map so that users could quickly move to another area without having to zoom out and locate it themselves. The code for the dropdown looks like this:
dcc.Dropdown([
'Contiguous U.S.', 'Alaska', 'Hawaii',
'Puerto Rico & the U.S. Virgin Islands',
'Northern Mariana Islands'
], 'Contiguous U.S.', id='map-dropdown'),
I then proceeded to create the callback function to do this:
@app.callback(
Output('graph', 'figure'), # this is what I want to change
Input('map-dropdown', 'value')
)
def change_map_view(value):
"""Change map center and zoom depending on selection"""
pass
The problem is that I don't actually want to regenerate the entire figure. Doing so would require re-fetching the data and regenerating the graph which is very slow. Thus, I don't need the output to be figure
but instead a subproperty of figure
: figure.layout.mapbox
, which contains the center and zoom information. However, when I tried to replace the Output
part of the decorator to use figure.layout.mapbox
, I get an error saying that the character .
is not allowed in the second argument to the Output
function.
So far, I have not been able to find a way to trigger a change in map perspective without regenerating the entire map. If there is any way to either change the figure.layout.mapbox
property as an output only or somehow alter the map as it is without regenerating it, that would be an ideal solution.
Upvotes: 0
Views: 582
Reputation: 205
Seems it's possible to do this without regenerating the map by just updating the layout and then returning the figure in the callback like so:
@app.callback(
Output('graph', 'figure'),
Input('map-dropdown', 'value')
)
def change_map_view(value):
"""Change map center and zoom depending on selection"""
fig.update_layout(
mapbox_style='open-street-map',
mapbox_zoom=new_zoom,
mapbox_center=new_center,
)
return fig
Didn't realize that variables from the outer scope can be accessed in callbacks, which fixes the problem.
Upvotes: 0