✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🧬 Learn how to build RNA-Seq data apps with Python & Dash. Register for the May 20 Webinar!

Dash - two maps zoom level synchronization

Hi all,

Could you advise how following could be implemented:

  • page contains two maps on right and left initially showing the same region, but displaying different statistical data (e.g scenario 1 and two)
  • when user make zoom in or out of left table, right table get the same zoom level?

Is that something can be achieved using call backs?
how?

Thank you,
Alexander

Did you ever figure this out? I have the same question.

@MichaelTiemann here’s a simplified example of how you can control one map via another map when you zoom in/out of first map and apply the same update to the second map:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import plotly.express as px
import dash_bootstrap_components as dbc

df = px.data.election()
geojson = px.data.election_geojson()
candidates = df.winner.unique()

fig2 = px.choropleth(
        df, geojson=geojson, color="Bergeron",
        locations="district", featureidkey="properties.district",
        projection="mercator", range_color=[0, 6500])
fig2.update_geos(fitbounds="locations", visible=False)
fig2.update_layout(margin={"r":0,"t":0,"l":0,"b":0})

app = dash.Dash(__name__)

app.layout = html.Div([
    html.P("Candidate:"),
    dcc.RadioItems(
        id='candidate', 
        options=[{'value': x, 'label': x} 
                 for x in candidates],
        value=candidates[0],
        labelStyle={'display': 'inline-block'}
    ),
    dcc.Graph(id="choropleth"),
    html.P("default map data", id="map_data"),
    dcc.Graph(id="choropleth2", figure=fig2)
])

@app.callback(
    Output("choropleth", "figure"), 
    [Input("candidate", "value")])
def display_choropleth(candidate):
    fig = px.choropleth(
        df, geojson=geojson, color=candidate,
        locations="district", featureidkey="properties.district",
        projection="mercator", range_color=[0, 6500])
    fig.update_geos(fitbounds="locations", visible=False)
    fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})

    return fig

@app.callback(Output('choropleth2', 'figure'),
             [Input('choropleth', 'relayoutData')])
def graph_event(select_data):
    fig2.update_layout(select_data)
    return fig2

app.run_server(debug=True)
1 Like

@DeejL thank you so much for your response! I’m pretty new to all this, and trying to focus on the plotly/ipywidgets side of things for my Jupyter Notebooks. I’ll work on building the map between your dash-based example and my Notebook-based world. If there’s a straightforward translation between @app.callback and observe for widgets, please let me know. Thanks!

All of the plotly objects (charts, maps etc.) will work exactly the same way in Jupyter notebooks as they do in an application like Dash. If you’d also like to integrate Dash into Jupyter notebook environment, here’s a great resource to use: Can I run dash app in jupyter - #5 by chriddyp

Good luck!

Here is the magic for which I was looking:

g = go.FigureWidget(fig)
def handle_zoom(layout, mapbox_zoom):
    print('new mapbox_zoom:', mapbox_zoom)
g.layout.on_change(handle_zoom, 'mapbox_zoom')

This work seamless, however, what if we want update the second graph properties too? e.g. instead of having fig2 outside of a callback, I would like to be able to change the behaviour accordingly to the candidate. Is it possible? I made some test but without success (the synchronized zoom will stop working)