In a scatter_3d
I have pairs of points that have the same x/y-coordinates but different z-coordinates.
When hovering over one of these pair partners, I want both to be highlighted (e.g. different color).
My original application has huge figures, that’s why creating the figure anew every time a hoverData
event is recorded is not practical.
Now I’m trying to do this with a clientside_callback
. I came across Plotly.restyle
but don’t know,
how to use it properly.
I created the following minimal example:
from dash import Dash, html, dcc
from dash.dependencies import Input, Output, State, ClientsideFunction
import plotly.express as px
import pandas as pd
app = Dash(__name__)
data = {'x': [1, 1, 2, 2, 3, 3],
'y': [1, 1, 2, 2, 3, 3],
'z': [1, 2, 2, 3, 3, 4]}
df = pd.DataFrame(data)
fig = px.scatter_3d(df, x='x', y='y', z='z', hover_data=df.columns)
app.layout = html.Div([
dcc.Graph(figure=fig, id='fig', style={'height': 'inherit'})
], style={'height': '100vh'})
app.clientside_callback(
ClientsideFunction(namespace='clientside', function_name='hover_3d'),
Output('fig', 'className'),
Input('fig', 'hoverData'),
State('fig', 'figure'), prevent_initial_call=True)
if __name__ == '__main__':
app.run_server(debug=True)
/* JavaScript namespaces */
if (!window.dash_clientside) {
window.dash_clientside = {};
}
window.dash_clientside.clientside = {
hover_3d: function(hover_data, fig) {
// get hover x/y coordinates
var hover_x = hover_data['points'][0]['x'];
var hover_y = hover_data['points'][0]['y'];
// loop through traces of figure ...
for (let i=0; i<fig['data'].length; i++) {
var trace_data = fig['data'][i];
var colors = [];
// ... loop through points in traces ...
for (let j=0; j<trace_data['x'].length; j++) {
// ... until we found a point that has the same x/y coordinates as the hovered point
// namely: the hover point itself and its partner
if ((hover_y == trace_data['y'][j]) && (hover_x == trace_data['x'][j])){
// paint these two red
colors.push('red');
} else {
// and leave the rest in the color they were
colors.push(fig['data'][i]['marker']['color']);
}
}
var update = {'marker':{color: colors, size:29}};
// try 1:
fig['data'][i]['marker'] = update['marker']
console.log(fig['data'][i]);
// try 2:
//Plotly.restyle('fig', update, [i]);
}
return window.dash_clientside.no_update;
}
}
try 1 is trying to hard set the changed properties to the figure’s trace which works but does not get applied.
try 2 is trying to use the Plotly.restyle
function but can’t, as it is obviously not defined.