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

如何在Dash Plotly中通过回调实时更新图表且保留布局?

实时更新Plotly图表的回调实现问题

我已经多方查找资料,但还是没法正确构建回调来实时更新图表,希望大家给点建议。我的目标是通过Arduino接收传感器数据,目前先用随机值做绘图测试。

以下是我绘制温度图表的初始代码:

graph_temperature = go.Figure(layout={"template": "plotly_dark"})
graph_temperature.add_trace(
    go.Scatter(x=df["tempo"], y=df["temp_obj"], name="temp_obj", mode="lines", line=dict(color="#F6511D")))
graph_temperature.add_trace(
    go.Scatter(x=df["tempo"], y=df["temp_amb"], name="temp_amb", mode="lines", line=dict(color="#FFB400")))
graph_temperature.update_layout(yaxis_title="Temperatura CVT", margin=dict(l=5, r=5, t=5, b=5), autosize=True,
                                height=150)

我该怎么编写回调来更新这类图表,同时保留原有布局?下面是我未完成的回调代码框架:

@app.callback(
    [
        Output('graph_temperature', 'figure'),
        # Output('graph_velocidade', 'figure'),
        # Output('graph_RPM', 'figure'),
        # Output('graph_ACC', 'figure'),
        # Output('graph_laps', 'figure'),
    ],
    Input('interval-component', 'n_intervals')
)
def update_graphs(num):
    if num == 0:
        raise PreventUpdate
    else:
        graph_temperature = {

        }

解决方案

要实现实时更新且保留原有布局,可按以下方式修改回调:

1. 抽离复用布局配置

把图表的基础样式(模板、标题、边距等)单独定义成变量,避免每次更新重复写布局代码:

# 全局复用的温度图表布局配置
temp_graph_layout = {
    "template": "plotly_dark",
    "yaxis_title": "Temperatura CVT",
    "margin": dict(l=5, r=5, t=5, b=5),
    "autosize": True,
    "height": 150
}

2. 完善回调逻辑

在回调中生成新数据、更新DataFrame,再基于复用的布局创建新图表:

import random

@app.callback(
    Output('graph_temperature', 'figure'),
    Input('interval-component', 'n_intervals')
)
def update_graphs(num):
    if num == 0:
        raise PreventUpdate
    
    # 模拟生成新数据(后续替换为Arduino串口读取逻辑)
    new_time = df["tempo"].iloc[-1] + 1
    new_temp_obj = random.uniform(20, 50)
    new_temp_amb = random.uniform(15, 30)
    
    # 追加新数据到DataFrame,限制仅保留最近50条避免卡顿
    df.loc[len(df)] = {"tempo": new_time, "temp_obj": new_temp_obj, "temp_amb": new_temp_amb}
    df = df.tail(50)
    
    # 基于复用布局创建新图表
    fig = go.Figure(layout=temp_graph_layout)
    fig.add_trace(go.Scatter(x=df["tempo"], y=df["temp_obj"], name="temp_obj", mode="lines", line=dict(color="#F6511D")))
    fig.add_trace(go.Scatter(x=df["tempo"], y=df["temp_amb"], name="temp_amb", mode="lines", line=dict(color="#FFB400")))
    
    return fig

关键注意事项

  • 数据量控制:持续追加数据会导致图表加载变慢,建议用df.tail(N)限制仅展示最近N条数据
  • 状态管理:如果是多用户场景,不要用全局DataFrame,改用dcc.Store组件存储数据状态更安全
  • Arduino适配:把模拟数据生成部分替换为pyserial读取串口数据的逻辑,注意处理数据解析和异常
  • 多图表扩展:要更新其他图表时,只需为每个图表定义对应的布局配置,在回调中依次生成返回即可

内容的提问来源于stack exchange,提问作者Gustavo de Araujo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 03:16:25