Announcing Dash Bio 1.0.0 🎉 : a one-stop-shop for bioinformatics and drug development visualizations.

Zoom or pan one Graph to zoom or pan in other Graph


I am looking for a method where we will zoom/pan in one graph which results in Zoom/Pan in other Graph.

Is it possible to do?

Sanjaya G prakash.

1 Like

Seems like you could listen to the relayoutData property of one chart and then update the figure.layout.xaxis.range property of different graph. See for a starting point.

1 Like

Thanks @chriddyp I got it now


I’m having trouble with the output to the second graph. Can someone or Sanjayagp show an example on how to do it?

Input(“graph1”, “relayoutData”),
should the output be:
Output(“graph2”, “relayoutData”),
Output(“graph2”, “figure.layout.xaxis.range”),

And if it is the second, in what format should the callback return the values to the output?

Any help is much appreciated.

@sanjayagp Here is the code snippet for synchronizing zoom in plotly dash


app.layout = html.Div([
                html.Pre(id='relayout-data', style=styles['pre']),
                dcc.Graph(id='graph2', figure=fig)])

# Just to see what values are captured.
@app.callback(Output('relayout-data', 'children'),
              [Input('graph', 'relayoutData')])
def display_relayout_data(relayoutData):
    return json.dumps(relayoutData, indent=2)

@app.callback(Output('graph2', 'figure'),
             [Input('graph', 'relayoutData')], 
             [State('graph2', 'figure')])
def graph_event(select_data,  fig):
       fig['layout'] = {'xaxis':{'range':[select_data['xaxis.range[0]'],select_data['xaxis.range[1]']]}}
    except KeyError:
       fig['layout'] = {'xaxis':{'range':[zoomed out value]}}
return fig

1 Like

I couldn’t quite get your example to work and ended up with the following.

My use case dynamically adds graphs by

dcc.Graph({'type': 'graph', 'index': index_counter})

Linking the zoom behavior

    Output({'type': 'graph', 'index': ALL}, 'relayoutData'),
    Output({'type': 'graph', 'index': ALL}, 'figure'),
    Input({'type': 'graph', 'index': ALL}, 'relayoutData'),
    State({'type': 'graph', 'index': ALL}, 'figure'))
def LinkedZoom(relayout_data, figure_states):
    unique_data = None
    for data in relayout_data:
      if relayout_data.count(data) == 1:
        unique_data = data
    if unique_data:
      for figure_state in figure_states:
        if unique_data.get('xaxis.autorange'):
          figure_state['layout']['xaxis']['autorange'] = True
          figure_state['layout']['yaxis']['autorange'] = True
          figure_state['layout']['xaxis']['range'] = [
              unique_data['xaxis.range[0]'], unique_data['xaxis.range[1]']]
          figure_state['layout']['xaxis']['autorange'] = False
          figure_state['layout']['yaxis']['range'] = [
              unique_data['yaxis.range[0]'], unique_data['yaxis.range[1]']]
          figure_state['layout']['yaxis']['autorange'] = False
      return [unique_data] * len(relayout_data), figure_states
    return relayout_data, figure_states

Reference: Link graph zoom · djhedges/exit_speed@863efbf · GitHub

1 Like