go.Scattergl disappears but go.Scatter does not (Animation using Shapes)

Hello plotly community!

I have a scatterplot with animation on top using shapes. The animation works fine as long as I use go.Scatter:

animate-scatter

The animation resembles how a single point changed position over time. You can see the dots as places and the user as moving from place to place.

The app functions as follows:

  1. User provides initial location
  2. User adds another location
  3. Hit “play” or repeat step 2;

I use shapes to draw the animation, which enables me to use animations on scattergl. Given there are many datapoints, go.Scatter is not suitable.

Here’s what happens after I add the next location using scattergl (note that I repeat the animation by hitting play after it finishes):

animation-scattergl-0

All good, but then… As soon as I add another location to the history of the user, the scattergl disappears.

animation-scattergl-1

Code details can be found here

I have tried many things:

  1. redraw=True # same issues + super slow
  2. delete figure and / or re-use figure data
  3. Replace the entire dcc.Graph instead its figure property
  4. reduce number of frames because perhaps had to do with this

I’m really dumbfound on this one.

I found a workaround. The issue is interesting, because hoverdata exists. So, although you don’t see the points, when I enable hoverinfo I do see the data when hovering over the points that disappear.

My workaround:

create two figures. One for the persistent data (i.e. scattergl with all the points) and one separately for the animated shape. So a dcc.Graph with the base-figure, and one with overlay-figure. Just make sure the layout is the same.

To overlay them on eachother, some css is needed. Mainly: dcc.Graph must have css styling with positions set to absolute. zIndex is to control ordering. Secondly, the parent container should have position set to relative. In my example below, I use dash bootstrap column.

 dbc.Col(
        id='fig-div',
        children=[
            dcc.Graph(
                id='base-figure',
                figure=base_fig,
                responsive=True,
                style={
                    "width": "100%", 
                    "height": "100%", 
                    'position': 'absolute', # must be absolute
                    'zIndex': 1 # controls layer its drawn on
                },
                config=DCC_GRAPH_CONFIG,
            ),
            dcc.Graph(
                id='overlay-figure',
                figure=overlay_fig,
                responsive=True,
                style={
                    "width": "100%",
                    "height": "100%",
                    'position': 'absolute',
                    'zIndex': 2
                },
                config={
                    'displayModeBar': False,
                    'editable': False,
                    'edits': {
                        'shapePosition': True,
                    }
                },
            )
        ],
        # This is the parent-style of the dcc which must have positions relative
        style={'position': 'relative'}
    )

Additional notes that might have some effects: when creating the base_fig I used scattergl, therefore, when creating the overlay_fig, i created the initial figure with an empty scattergl.