Hover event in scatter_3d plot, coordinates changed

Hello,

I defined a hover event, where I will give a special color to the hovered point, and return the 3d plot.

In terms of the color assignment, i just update the trace, as the coding below
fig[‘data’][0][‘marker’][‘color’][k] = marker_color[i]
fig[‘data’][0][‘marker’][‘size’][k] = marker_size[i]
fig[‘data’][0][‘marker’][‘symbol’][k] = marker_symbol[i]

It works well, but there is one drawback:

For example, I have rotated my 3d plot to a specific angle. Once the hover event was triggered, the system assigned a new color to the hovered point, but also reset the coordinates. In other words, the previous zoom status or rotation status was missing.

Any solutions or hints to assign the color to the hovered point, but no changes on the zoom and rotation status?

I tried to save layout when I acquire the 3d plot from callback function,

and save this layout back before return the 3d plot
fig_3d[‘layout’] = layout_3d

But, this does not work for me

Hi @irecsys you can use partial updates for this:

import dash
from dash import dcc, html, Input, Output, callback, Patch
import plotly.graph_objs as go


fig = go.Figure(
    data=go.Scatter3d(
        x=[1, 2, 3],
        y=[1, 2, 3],
        z=[1, 2, 3],
        mode='markers',
        marker={'color': ['red', 'red', 'red']}
    ),
    layout={'width': 700, 'height': 700}
)

app = dash.Dash(__name__)
app.layout = html.Div(
    [
        dcc.Graph(id='graph', figure=fig),
    ]
)


@callback(
    Output('graph', 'figure'),
    Input('graph', 'hoverData'),
    prevent_initial_call=True
)
def update_color(hoverData):
    # get infor concerning trace id and point id
    trace_idx = hoverData['points'][0]['curveNumber']
    point_idx = hoverData['points'][0]['pointNumber']

    # initial colors
    colors = ['red', 'red', 'red']

    # change color at point index
    colors[point_idx] = 'blue'

    # patch the figure
    patched = Patch()
    patched['data'][trace_idx]['marker']['color'] = colors
    return patched


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