You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Plotly高亮功能控制图例交互:实现点击图例高亮数据点

实现Plotly Dash图例点击高亮对应数据点

需求说明

原代码实现的是点击图例时对应数据点透明度降低(近似隐藏),现需修改为点击图例时高亮对应数据点(即目标数据点保持高可见度,其余数据点降低透明度,或切换目标数据点的高亮状态)。

修改后的代码

import plotly.graph_objects as go
import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import plotly.express as px

# 加载iris数据集
iris = px.data.iris()

app = dash.Dash(__name__)

# 初始化散点图:所有trace默认低透明度,方便高亮对比
fig = go.Figure()
for s in iris['species'].unique():
    subset = iris[iris['species'] == s]
    fig.add_trace(go.Scatter(
        x=subset['petal_length'],
        y=subset['petal_width'],
        mode='markers',
        name=s,
        marker=dict(opacity=0.3)  # 初始低透明度
    ))

# 禁用Plotly默认的图例点击隐藏/显示行为,自定义交互
fig.update_layout(
    legend=dict(
        itemclick=False,  # 禁用单点击默认行为
        itemdoubleclick=False  # 禁用双击默认行为
    )
)

app.layout = html.Div([
    dcc.Graph(id='iris-plot', figure=fig),
])

@app.callback(
    Output('iris-plot', 'figure'),
    Input('iris-plot', 'relayoutData'),
    prevent_initial_call=True  # 防止初始加载触发回调
)
def highlight_trace(relayoutData):
    # 捕捉图例点击事件
    if relayoutData and 'legend.clickeditems' in relayoutData:
        clicked_item = relayoutData['legend.clickeditems'][0]
        curve_number = clicked_item['curveNumber']
        
        # 复制当前figure,避免修改原始全局figure
        updated_fig = go.Figure(fig)
        
        # 切换目标trace的透明度:点击时高亮(opacity=1),再次点击恢复低透明度(0.3)
        current_opacity = updated_fig.data[curve_number].marker.opacity
        new_opacity = 1 if current_opacity == 0.3 else 0.3
        updated_fig.data[curve_number].marker.opacity = new_opacity
        
        return updated_fig
    # 未触发图例点击时返回原figure
    return fig

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

关键改动说明

  1. 初始透明度设置:将所有数据点的初始opacity设为0.3,让未高亮的点处于低可见度状态,高亮时切换为1,形成明显视觉对比。
  2. 禁用默认图例行为:通过fig.update_layout(legend=dict(itemclick=False, itemdoubleclick=False))关闭Plotly默认的图例点击隐藏/显示功能,确保自定义交互逻辑生效。
  3. 事件捕捉修正:将回调输入从clickData改为relayoutData,因为图例点击属于布局重排事件,clickData仅捕捉数据点的点击操作。
  4. 无副作用修改:在回调中创建原figure的副本updated_fig,而非直接修改全局的fig,符合Dash回调的无状态要求。
  5. 状态切换逻辑:根据点击状态切换目标trace的透明度,实现“点击高亮、再次点击取消高亮”的交互效果。

如果需要实现每次仅高亮单个类别(点击图例时,只有目标类别保持高透明度,其余类别均为低透明度),可修改回调逻辑如下:

@app.callback(
    Output('iris-plot', 'figure'),
    Input('iris-plot', 'relayoutData'),
    prevent_initial_call=True
)
def single_highlight_trace(relayoutData):
    if relayoutData and 'legend.clickeditems' in relayoutData:
        clicked_item = relayoutData['legend.clickeditems'][0]
        curve_number = clicked_item['curveNumber']
        
        updated_fig = go.Figure(fig)
        # 遍历所有trace:目标trace设为1,其余设为0.3
        for i in range(len(updated_fig.data)):
            updated_fig.data[i].marker.opacity = 1 if i == curve_number else 0.3
        
        return updated_fig
    return fig

内容的提问来源于stack exchange,提问作者user2940774

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 22:42:08