如何在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
相关产品推荐
相关产品推荐

