Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change Color of an Entire Trace on Hover/Click in Plotly

I have the current figure in plotly (jupyter notebook code below), and was hoping to create the effect whereby when you hover or click over each trace, the whole trace is highlighted a different colour (in this example red). I tried implementing these examples from SOF: Plotly in Python: how to highlight a trace on hover? & How do I highlight an entire trace upon hover in Plotly for Python? with no luck. If anyone could help that would be amazing. Currently each trace remains lightgrey.

import plotly.graph_objects as go

teams_list = sorted(teams_list,key=str.lower)
default_linewidth = 2
highlighted_linewidth_delta = 2

fig = go.FigureWidget() 
f.layout.hovermode = 'closest'
f.layout.hoverdistance = -1 #ensures no "gaps" for selecting sparse data

for t in teams_list:
    fig.add_trace(go.Scatter(x=elo_all.index, 
                             y=elo_all[t],
                             name=t,
                             mode='lines',
                             text=elo_all['Round'], # hover text goes here
                             line={'width': default_linewidth, 'color':'lightgrey'}))

    
fig.update_layout(
    xaxis = dict(
        tickmode = 'array',
        tickvals = [0,29,58,87,117,146],
        ticktext = [2015,2016,2017,2018,2019,2020]
    )
)


# our custom event handler
def update_trace(trace, points, selector):
    # this list stores the points which were clicked on
    # in all but one event they it be empty
    if len(points.point_inds) > 0:
        for i in range( len(fig.data) ):
            fig.data[i]['line']['color'] = 'red'



# we need to add the on_click event to each trace separately       

for i in range(len(fig.data)):
    fig.data[i].on_hover(update_trace)

# show the plot
fig.show()

enter image description here

like image 493
MSalty Avatar asked Sep 20 '25 02:09

MSalty


1 Answers

So this was a problem in 2 parts as it turns out:

  1. The problem for me was that the widgets extension had not been enabled correctly (as I could check from executing jupyter nbextension list, the output was empty), which is why the fig would not render without .show() and why the on_click function did not work. You can fix this by first checking jupyter nbextension list, if it’s empty can you try in your conda env:
jupyter nbextension enable --py widgetsnbextension
  1. I fixed my script above to the below which works perfectly, sadly I don't have a gif of it in action yet.
    import plotly.graph_objects as go
    
    teams_list = sorted(teams_list,key=str.lower)
    default_linewidth = 2
    highlighted_linewidth = 3
    
    fig = go.FigureWidget() # hover text goes here
    fig.layout.hovermode = 'closest'
    fig.layout.hoverdistance = -1 #ensures no "gaps" for selecting sparse data
    
    for t in teams_list:
        fig.add_trace(go.Scatter(x=elo_all.index, 
                                 y=elo_all[t],
                                 name=t,
                                 mode='lines',
                                 text=elo_all['Round'],
                                 opacity=0.3,
                                 line={'width': default_linewidth, 'color':'grey'}))
    
        
    fig.update_layout(
        xaxis = dict(
            tickmode = 'array',
            tickvals = [0,29,58,87,117,146],
            ticktext = [2015,2016,2017,2018,2019,2020]
        )
    )
    
    fig.update_yaxes(range=[1350, 1650])
    
    # our custom event handler
    def update_trace(trace, points, selector):
        if len(points.point_inds)==1:
            i = points.trace_index
            for x in range(0,len(fig.data)):
                fig.data[x]['line']['color'] = 'grey'
                fig.data[x]['opacity'] = 0.3
                fig.data[x]['line']['width'] = default_linewidth
            #print('Correct Index: {}',format(i))
            fig.data[i]['line']['color'] = 'red'
            fig.data[i]['opacity'] = 1
            fig.data[i]['line']['width'] = highlighted_linewidth
    
    # we need to add the on_click event to each trace separately       
    for x in range(0,len(fig.data)):
        fig.data[x].on_click(update_trace)
    
    # show the plot
    fig
like image 73
MSalty Avatar answered Sep 21 '25 16:09

MSalty