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

Plotly多y轴图表如何实现点击曲线时动态显隐对应关联坐标轴

可以实现,核心思路是监听图例点击事件,将trace的显隐状态和对应y轴的显隐状态绑定。下面分两种常用场景给出实现方案:

方案1:生成独立HTML文件(无需后端,纯前端交互)

这个方案通过注入JavaScript事件监听代码实现,不需要额外的服务支撑,生成的HTML可以直接打开使用。

import plotly.graph_objects as go
from plotly.subplots import make_subplots

# 创建带双y轴的画布
fig = make_subplots(specs=[[{"secondary_y": True}]])

# 添加轨迹,注意每个轨迹对应yaxis属性,默认第一个是'y',第二个是'y2'
fig.add_trace(
    go.Scatter(x=[1, 2, 3], y=[40, 50, 60], name="yaxis data"),
    secondary_y=False,
)

fig.add_trace(
    go.Scatter(x=[2, 3, 4], y=[4, 5, 6], name="yaxis2 data"),
    secondary_y=True,
)

# 基础配置
fig.update_layout(
    title_text="双Y轴同步显隐示例",
    xaxis_title="x轴标题",
    yaxis_title="<b>主</b>y轴标题",
    yaxis2_title="<b>次</b>y轴标题"
)

# 注入JavaScript实现同步显隐逻辑
js_code = """
const plotlyElement = document.getElementById('{plot_id}');
plotlyElement.on('plotly_restyle', function(data) {
    const update = {};
    // 统计每个y轴下是否存在可见轨迹
    const axisVisibleMap = {};
    plotlyElement.data.forEach(trace => {
        const yAxisKey = trace.yaxis || 'y';
        const isTraceVisible = trace.visible !== 'legendonly' && trace.visible !== false;
        axisVisibleMap[yAxisKey] = axisVisibleMap[yAxisKey] || isTraceVisible;
    });
    // 批量更新y轴显隐状态
    Object.keys(axisVisibleMap).forEach(key => {
        update[`${key}.visible`] = axisVisibleMap[key];
    });
    Plotly.relayout(plotlyElement, update);
});
"""
# 将JS代码添加到图中
fig.add_js_funcs(js_code)

# 生成HTML文件或者直接显示
fig.write_html("multi_y_sync.html")
fig.show()

如果是3个及以上y轴的情况,只需要在创建子图的时候定义好对应的y轴,添加轨迹时指定yaxis参数对应到'y3'、'y4'即可,上面的JS逻辑可以自动适配,不需要修改。

方案2:Dash应用场景

如果是在Dash框架中开发交互式应用,可以直接用Python回调实现,不需要写JS:

from dash import Dash, dcc, html, Input, Output, State, callback
import plotly.graph_objects as go
from plotly.subplots import make_subplots

app = Dash(__name__)

# 初始化图表
def init_fig():
    fig = make_subplots(specs=[[{"secondary_y": True}]])
    fig.add_trace(
        go.Scatter(x=[1, 2, 3], y=[40, 50, 60], name="yaxis data"),
        secondary_y=False,
    )
    fig.add_trace(
        go.Scatter(x=[2, 3, 4], y=[4, 5, 6], name="yaxis2 data"),
        secondary_y=True,
    )
    fig.update_layout(
        title_text="双Y轴同步显隐示例",
        xaxis_title="x轴标题",
        yaxis_title="<b>主</b>y轴标题",
        yaxis2_title="<b>次</b>y轴标题"
    )
    return fig

app.layout = html.Div([
    dcc.Graph(id="multi-y-graph", figure=init_fig())
])

@callback(
    Output("multi-y-graph", "figure"),
    Input("multi-y-graph", "restyleData"),
    State("multi-y-graph", "figure"),
    prevent_initial_call=True
)
def sync_y_axis(restyle_data, fig):
    traces = fig['data']
    layout = fig['layout']
    # 统计每个y轴下是否有可见的轨迹
    y_axis_visibility = {}
    for trace in traces:
        y_key = trace.get('yaxis', 'y')
        visible = trace.get('visible', True)
        is_visible = visible not in ('legendonly', False)
        y_axis_visibility[y_key] = y_axis_visibility.get(y_key, False) or is_visible
    # 更新布局
    for y_key, visible in y_axis_visibility.items():
        axis_key = y_key if y_key.startswith('yaxis') else f"{y_key}axis"
        if axis_key in layout:
            layout[axis_key]['visible'] = visible
    return fig

if __name__ == "__main__":
    app.run_server(debug=True)
注意事项
  • 如果多个轨迹绑定同一个y轴,上面的逻辑会自动判断:只有该y轴下所有轨迹都被隐藏时,y轴才会隐藏,只要有一个轨迹显示,y轴就保持显示
  • 3个及以上y轴的场景,只需要在创建图表时正确配置每个轨迹对应的yaxis参数即可,逻辑无需调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 00:45:06