Skip to content

[BUG] Animated Graph Conflicts with Animated Figure #1474

Closed
@ghost

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:

Expected Result

Observed 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)

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions