[BUG] Animated Graph Conflicts with Animated Figure #1474
![@ghost](https://github.com/ghost.png?size=80)
Description
Thank you so much for helping improve the quality of Dash!
We do our best to catch bugs during the release process, but we rely on your help to find the ones that slip through.
Describe your context
My Dash Server is hosted on WSL2, and browse the App from my browser.
- result of
pip list | grep dash
:
dash 1.17.0
dash-core-components 1.13.0
dash-html-components 1.1.1
dash-renderer 1.8.3
dash-table 4.11.0
-
Browser, Version and OS, reproduced on both Firefox and Edge:
- OS: Windows 10 64 bits
- Browser: Firefox, Edge
- Version: Firefox 83.0, Edge 87.0
Describe the bug
When both dcc.Graph
and go.Figure
have animation, then, when the second animation in Figure
is executed, the Frames
from the first animation are played instead of the second one. There is also a change in the dataset to display.
My findings showed that all the data is correctly sent by the server, and is shown in the callback debug UI. I could not pinpoint exactly where the bug occurs in the JavaScript code as my knowledge is limited. See screenshots for more information.
Expected behavior
The animation from the second (and following) request should be played instead of the animation of the first requested data.
Screenshots
Sorry for the quality of the GIFs!
Expected result:
Observed result:
Reproducible App
Use the following snippet to reproduce easily the issue:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
fig = go.Figure(
data=[],
layout=go.Layout(
title='Select a dataset to play',
yaxis=dict(range=[-1, 5]),
xaxis=dict(range=[-3, 3]),
updatemenus=[dict(type="buttons",
buttons=[dict(label="Play",
method="animate",
args=[None, {"frame": {"duration": 100, "redraw": True},
"fromcurrent": False,
"transition": {"duration": 500,
"easing": "quadratic-in-out"}}])])]
),
frames=[],
)
app.layout = html.Div([
html.Label('Choose dataset'),
dcc.RadioItems(
id='change-data',
options=[
{'label': 'No data', 'value': 0},
{'label': 'Data A', 'value': 1},
{'label': 'Data B', 'value': 2}
],
value=0,
),
dcc.Graph(id='test-change', animate=True, # Set the falue to False to workaround the bug
animation_options={"frame": {"redraw": True}}), # Tried with redraw set to True or False with same result
])
@app.callback(
Output('test-change', 'figure'),
Input('change-data', 'value'),
)
def set_data(dataset):
if dataset == 1:
title = 'Dataset A'
data = go.Scatter(
x=[0, 1, 2],
y=[0, 1, 2],
mode='markers',
)
frames = [
go.Frame(
data=go.Scatter(
x=[0, 1, 2],
y=[1, 2, 3],
mode='markers',
)
),
go.Frame(
data=go.Scatter(
x=[0, 1, 2],
y=[2, 3, 4],
mode='markers',
)
)
]
elif dataset == 2:
title = 'Dataset B'
data = go.Scatter(
x=[0, -1, -2],
y=[0, 1, 2],
mode='markers',
)
frames = [
go.Frame(
data=go.Scatter(
x=[0, -1, -2],
y=[1, 2, 3],
mode='markers',
)
),
go.Frame(
data=go.Scatter(
x=[0, -1, -2],
y=[2, 3, 4],
mode='markers',
)
)
]
else:
title = 'Select a dataset'
data = []
frames = []
return go.Figure(
data=data,
layout=go.Layout(
title=title,
yaxis=dict(range=[-1, 5]),
xaxis=dict(range=[-3, 3]),
updatemenus=[dict(type="buttons",
buttons=[dict(label="Play",
method="animate",
args=[None, {"frame": {"duration": 100, "redraw": False}, # Tried with redraw set to False with same result
"fromcurrent": False,
"transition": {"duration": 500,
"easing": "quadratic-in-out"}}])])]
),
frames=frames,
)
if __name__ == "__main__":
app.run_server(debug=True)