更新痕迹Graph
组件无需生成新的图形对象可以通过以下方式实现extendData
财产。这是一个每秒附加数据的小例子,
import dash
import dash_html_components as html
import dash_core_components as dcc
import numpy as np
from dash.dependencies import Input, Output
# Example data (a circle).
resolution = 20
t = np.linspace(0, np.pi * 2, resolution)
x, y = np.cos(t), np.sin(t)
# Example app.
figure = dict(data=[{'x': [], 'y': []}], layout=dict(xaxis=dict(range=[-1, 1]), yaxis=dict(range=[-1, 1])))
app = dash.Dash(__name__, update_title=None) # remove "Updating..." from title
app.layout = html.Div([dcc.Graph(id='graph', figure=figure), dcc.Interval(id="interval")])
@app.callback(Output('graph', 'extendData'), [Input('interval', 'n_intervals')])
def update_data(n_intervals):
index = n_intervals % resolution
# tuple is (dict of new data, target trace index, number of points to keep)
return dict(x=[[x[index]]], y=[[y[index]]]), [0], 10
if __name__ == '__main__':
app.run_server()
根据客户端和服务器之间的网络连接(每次更新时,客户端和服务器之间交换请求),此方法的刷新率可达 1 秒左右。
如果您需要更高的刷新率,我建议使用客户端回调 https://dash.plotly.com/clientside-callbacks。采用前面的示例,代码将类似于
import dash
import dash_html_components as html
import dash_core_components as dcc
import numpy as np
from dash.dependencies import Input, Output, State
# Example data (a circle).
resolution = 1000
t = np.linspace(0, np.pi * 2, resolution)
x, y = np.cos(t), np.sin(t)
# Example app.
figure = dict(data=[{'x': [], 'y': []}], layout=dict(xaxis=dict(range=[-1, 1]), yaxis=dict(range=[-1, 1])))
app = dash.Dash(__name__, update_title=None) # remove "Updating..." from title
app.layout = html.Div([
dcc.Graph(id='graph', figure=dict(figure)), dcc.Interval(id="interval", interval=25),
dcc.Store(id='offset', data=0), dcc.Store(id='store', data=dict(x=x, y=y, resolution=resolution)),
])
app.clientside_callback(
"""
function (n_intervals, data, offset) {
offset = offset % data.x.length;
const end = Math.min((offset + 10), data.x.length);
return [[{x: [data.x.slice(offset, end)], y: [data.y.slice(offset, end)]}, [0], 500], end]
}
""",
[Output('graph', 'extendData'), Output('offset', 'data')],
[Input('interval', 'n_intervals')], [State('store', 'data'), State('offset', 'data')]
)
if __name__ == '__main__':
app.run_server()
客户端更新应该足够快,以实现平滑更新。下面的 gif 显示了以 25 毫秒刷新率运行的上述示例,
请记住,只有当数据已经存在于客户端时才可能进行客户端更新,即需要另一种机制来从服务器获取数据。可能的数据流可以是
- 使用慢速
Interval
组件(例如 2 秒)触发一个(正常)回调,从源中获取一块数据并将其放入Store
成分
- 使用快速
Interval
组件(例如 25 ms)触发客户端回调,该回调从Store
组件到Graph
成分