Black Lives Matter. Please consider donating to Black Girls Code today.

How to save current zoom and position after filtering?

Hi,
I have a Mapbox section with markers plotted on it. When I zoom on the markers after filtering the markers data with a slider, the map refreshes itself to its initial zoom and position.
Is it possible to save these 2 parameters after filtering ?
Thank you.

Good question. You can pass in the current figure or relayoutData as state and use the range values from that figure in the new figure that you create. Here’s an example: https://plot.ly/dash/gallery/new-york-oil-and-gas/ (see the “Lock camera” checkbox) and here’s the relevant section in the code: https://github.com/plotly/dash-oil-and-gas-demo/blob/d937ebbbf9da244d9832e25c42b46319148d9ef5/app.py#L437-L448

Here’s a simple example that shows the two types of modes with a cartesian plot:

import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html

import copy

app = dash.Dash()

FIGURE = {
    'data': [{
        'x': [1, 2, 3],
        'y': [4, 3, 6],
        'mode': 'markers',
        'marker': {
            'size': 8
        }
    }],
    'layout': {
        'xaxis': {},
        'yaxis': {},
    }
}

app.layout = html.Div([
    html.H3('Persistent Zoom on Updates'),
    html.Div('''
        Try zooming into the graph (clicking and dragging on the graph),
        then updating the text box. Notice how the graph does not zoom out
        when the graph is updated. Switching to "Refresh View" will
        redraw the graph with auto-range enabled.
    '''),
    dcc.Input(id='my-input'),
    dcc.RadioItems(
        id='lock-zoom',
        options=[{'label': i, 'value': i} for i in ['Lock View', 'Refresh View']],
        value='Lock View'
    ),
    dcc.Graph(
        id='my-graph',
        figure=FIGURE
    )
])

@app.callback(
    Output('my-graph', 'figure'),
    [Input('my-input', 'value'),
     Input('lock-zoom', 'value')],
    [State('my-graph', 'relayoutData')])
def update_graph(value, lock_zoom, relayout_data):
    new_figure = copy.deepcopy(FIGURE)
    new_figure['layout']['title'] = value

    # relayout_data contains data on the zoom and range actions
    print(relayout_data)
    if relayout_data and lock_zoom == 'Lock View':
        if 'xaxis.range[0]' in relayout_data:
            new_figure['layout']['xaxis']['range'] = [
                relayout_data['xaxis.range[0]'],
                relayout_data['xaxis.range[1]']
            ]
        if 'yaxis.range[0]' in relayout_data:
            new_figure['layout']['yaxis']['range'] = [
                relayout_data['yaxis.range[0]'],
                relayout_data['yaxis.range[1]']
            ]

    return new_figure

app.css.append_css({"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"})

if __name__ == '__main__':
    app.run_server(debug=True)

2 Likes

Thanks. But, is it possible to integrate a styled lock button inside the map ? like below

You’ll have to style the checkbox yourself. You could also remove the checkbox and have this as the default behaviour.