How can I update the info inside a mapbox without reloading the figure in plotly dash

2.1k views Asked by At

I'm using plotly's dash to try and build a simple dashboard which contains two widgets - a graph and a map (based on mapbox). The graph data points and the locations on the map are connected to each other and i'd like to highlight the relevant dot on the map when a user's mouse hovers over the relevant point on the graph.

I've tried using dash's callbacks with the following layout:

app = dash.Dash()
app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),

    html.Div(children='''
        Dash: A web application framework for Python.
    ''', id='xxx'),

    dcc.Graph(
        id='example-graph',
        figure=sl.draw_graph('Altitude')

    ),
    dcc.Graph(
        id='example-map',
        figure=sl.draw_map()
    ),

])

And the following callback:

@app.callback(
    Output('example-map', 'figure'),
    [Input('example-graph', 'hoverData')])

def display_hover_data(hoverData):
    figure = app.layout['example-map'].figure
    figure['data'].append(get_new_highlighted_dot(hoverData))
    return figure

Note that I realize that I should remove old highlighted dots - but that's not the point here.

This does the trick but requires the constant reloading of the mapbox figure which ruins the user experience. What I would like is just change the traces in the map without reloading the entire figure.

I've tried using the mydcc module which allows updating the data only without reloading the entire figure, but it still works slow when having thousands of traces on the map.

I was wondering if there is anyway to overcome this issues? I'm also open to using other similar python based technologies.

1

There are 1 answers

0
Oleh Rybalchenko On

You can make custom component based on Graph from dash core components and modify plotly hover event handler to send ajax request and get new point.

gd.on('plotly_hover', (eventData) => {
    const hoverData = filterEventData(gd, eventData, 'hover');
    if (!isNil(hoverData)) {
        // get data and redraw plot
        ajax_update_plot(id, hoverData); 

        if (setProps) setProps({hoverData});
        if (fireEvent) fireEvent({event: 'hover'})
    }
});

In ajax_update_plot retrieve data from server using regular AJAX way and update plot with updated data.

// get new point and add it to the graph
Plotly.addTraces(id, point);

Check the function declaration in documentation for addTraces

Yes, I realize that my solution is far from Dash natural way. But it seems that the framework itself has no efficient method for this (so far).