Mapbox zoom stops working once figure data is updated

Hi everyone,

I have an app that plots markers at site coordinates in a dcc.Graph using a list of plotly.graph_objs.Scattermapbox for the figure data and a plotly.graph_objs.Layout for the figure layout. I have a drop down menu at the top of my app where one selects a project and then the map updates to show the markers for only the project selected and changes the coordinates of the center of the map to be focus on the selected project. The problem I am having is that once I modify the data being used by the Graph, by changing the project drop down value or applying some other data filtering, I completely loose the ability to zoom in and out on the map with my mouse. This happens both if I have my callback update the figure attribute of a dcc.Graph in the static layout, or if I have my callback update an entire dcc.Graph into the children attribute of a html.Div in the static layout. I have provided a simplified version of my code that experiences this glitch below.

import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go

mapbox_access_token = 'XXXX'

app = dash.Dash(__name__)

df_all_sites = pd.DataFrame(
    {'proj': ['K', 'K', 'H', 'H'], 'id': ['SW', 'SK', 'RH', 'HVO'],
     'lat': [35.7189, 35.3347, 21.3711, 19.4201],
     'lon': [129.4803, 129.3100, -157.9053, -155.2879]}
)

layout1 = html.Div([
    html.H3('Select a Project'),
    dcc.Dropdown(
        id='dropdown',
        options=[{'label': 'Korea', 'value': 'K'},
                 {'label': 'Hawaii', 'value': 'H'}],
        value='H'
    ),
    html.H3('Map of Project Sites'),
    dcc.Graph(id='Map1-Graph')
])

app.layout = layout1


@app.callback(
    Output('Map1-Graph', 'figure'),
    [Input('dropdown', 'value')])
def update_map(proj):
    df_all_sites = pd.DataFrame(
        {'proj': ['K', 'K', 'H', 'H'], 'id': ['SW', 'SK', 'RH', 'HVO'],
         'lat': [35.7189, 35.3347, 21.3711, 19.4201],
         'lon': [129.4803, 129.3100, -157.9053, -155.2879]}
    )
    df_sites = df_all_sites[df_all_sites['proj'] == proj]
    dataMap = []
    dataMap.append(
        go.Scattermapbox(
            lat=df_sites['lat'],
            lon=df_sites['lon'],
            text=df_sites['id'],
            mode='markers',
            marker=dict(symbol='triangle', size=14, color='black'),
            opacity=1.0,
            name='Sites'
        )
    )
    layoutM1 = go.Layout(
        autosize=True,
        hovermode='closest',
        mapbox=dict(
            accesstoken=mapbox_access_token,
            bearing=0,
            center=dict(lat=df_sites.iloc[0]['lat'],
                        lon=df_sites.iloc[0]['lon']),
            pitch=0,
            zoom=5
        )
    )
    fig = dict(data=dataMap, layout=layoutM1)
    return fig


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

Please let me know you experience the same problem I have been and if you have any suggestions for a fix.
Please note you will need to replace ‘XXXX’ with an actual mapbox accesstoken for the above code to function

Thanks

This just started happening to me as well. I am pretty sure i had no problems up until today. Now any update to the data scope of the mapbox scatter causes this. Did you find a solution of any kind? This renders my entire map useless since you can’t zoom to the right region…

datadrinkr,

The only workaround I have implemented so far is to add a slider below the map that is an extra input for the map figure update callback that is used to set the zoom attribute in the plotly.graph_objs.Layout that servers as the layout portion of the map plotly.graph_objs.Figure figure object.

The following code segment is for the slider i put in my layout.

dcc.Slider(
        id='Map1-slider',
        min=0,
        max=16,
        marks={
            0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7',
            8: '8', 9: '9', 10: '10', 11: '11', 12: '12', 13: '13', 14: '14',
            15: '15', 16: '16'
        },
        value=5,
        step=0.5
),

The advantage of this approach is it allows the user a way to zoom the map, the big disadvantage is it always zooms centered on what you have as the center in your map layout. This requires the user to zoom first then pan to get a desired view. It’s not a great fix but at least it makes using the tool possible, just not convenient. Let me know if you come up with a better fix.

That is a creative way to work around this. However, i wouldn’t say its acceptable given that scrollwheel zoom was definitely working up until today/a few days ago. Also a slider really doesnt replace the fluidity of zooming in and out smoothly. You’re essentially redrawing the whole map every time u need to zoom in and out? That is a painful user experience. This is definitely a broken feature. Who can we raise this with to get it looked into?
@chriddyp, was this possibly caused by an update to mapbox that might have been pushed through this week? is there anything that can be done to restore the original functionality?

@chriddyp; @mwhaap
one clue is that in the initial load of a map, zooming works fine. Its only on that subsequent update that it breaks. Is there a difference in that initial page load vs the update in how the mapbox api is called?
Maybe that offers a way to sort of force a ‘full refresh’ and get the zooming back…

Thanks,

@mwhaap I have made some progress with another tactic. I added the following callback to my code (my scattermapbox trace is in a dcc.Graph with an id of ‘themap’. I’m essentially forcing the config to scrollzoom = True, with the guess that it was somehow being altered when the map is getting updated.

Adding this is working so far (fingers crossed!)

@app.callback(
dash.dependencies.Output(‘themap’,‘config’)
,[dash.dependencies.Input(‘themap’,‘figure’)]
)
def forcezoom(f):
return(dict(scrollZoom = True))

@datadrinkr Thanks for the update, your solution seems to be working for me also. I’m curious what references you used to come up with this tactic, nothing I came across in my searching indicated there was a scrollZoom attribute one could modify with a tuple of a dictionary sent to the dcc.Graph config. Did you go through a lot of source code on Git Hub?

Also see [SOLVED] ScatterMapBox Zoom Not Working After updating Input/Dropdown DCC

@mwhaap i found the config option by searching for options to enable scroll wheel zoom. ironically most of the results were people looking to disable it…

@chriddyp thanks! that looks even simpler. by the way what do you use to create those gifs you sometimes embed in your posts to demonstrate stuff? i could really use something like that…

LICEcap :slight_smile: Cockos Incorporated | LICEcap