Black Lives Matter. Please consider donating to Black Girls Code today.

Animation with slider not moving when pressing 'play'

Hello,

I’m trying to create an animation with a map and a slider.
Everything works well except the fact that when I launch the animation by pressing ‘play’ the slider does not update. However when I’m move the slider the map is correctly updated.

It’s like a bidirectional dependency working only in one way … I can’t figure out what I’m missing …

The following example sums up my problem and should be reproducible by updating the ‘mapbox_access_token’

import numpy as np
import pandas as pd
import json
import plotly.graph_objects as go
import urllib.request

# Import geospatial coordinates
fr_url = 'https://france-geojson.gregoiredavid.fr/repo/regions/ile-de-france/departements-ile-de-france.geojson'
with urllib.request.urlopen(fr_url) as url:
    jdata = json.loads(url.read().decode())

L = len(jdata['features'])
    
for k in range(L):
    jdata['features'][k]['id'] = f'{k}'
        
regions = []
code_dep = []
    
for feat in jdata['features']:
    regions.append(feat['properties']['nom'])
    code_dep.append(feat['properties']['code'])

# map layout 
mapbox_access_token = 'pk.'

layout = go.Layout(width = 770, height=650,
                  mapbox = dict(center= dict(lat=48.653, lon= 2.48),
                                accesstoken=mapbox_access_token,
                                zoom=7.5))

data = [go.Choroplethmapbox(locations = [jdata['features'][k]['id'] for k in range(L)],
                             z = np.random.randint(-10, 10,  size=L),
                             colorscale = pl_deep,
                             text =regions, 
                             zmin=-10,
                             zmax = 10,
                             #colorbar = dict(thickness=20, ticklen=3),
                             geojson = jdata,
                             marker_line_width=0, marker_opacity=0.7)]


date_range = ['2014', '2015', '2016', '2017', '2018']
frames = []

for q in date_range[1:]:
    frames.append( go.Frame(data=[go.Choroplethmapbox(locations = [jdata['features'][k]['id'] for k in range(L)],
                                z = np.random.randint(-10, 10,  size=L),
                                colorscale = pl_deep,
                                text =regions, 
                                zmin=-10,
                                zmax = 10,
                                colorbar = dict(thickness=20, ticklen=3),
                                geojson = jdata,
                                marker_line_width=0, marker_opacity=0.7)]
                          )
                  )

sliders = [dict(steps= [dict(method= 'animate',
                       args= [[ frames[k] ],
                              dict(mode= 'immediate',
                              frame= dict( duration=600, redraw= True ),
                                       transition=dict( duration= 100)
                                      )
                                ],
                        label='Date : {}'.format(date_range[k])
                         ) for k in range(0,len(frames))], 
            transition= dict(duration= 200 ),
            x=0,
            y=0,
            currentvalue=dict(font=dict(size=12), visible=True, xanchor= 'center'),
            len=1.0)
       ]

# Update Layout
layout.update(updatemenus=[dict(type='buttons', showactive=False,
                               y=0,
                               x=0,
                               xanchor='left',
                               pad=dict(t=5, r=10),
                               buttons=[dict(label='Play',
                                             method='animate',
                                             args=[None, 
                                                   dict(frame=dict(duration=600, 
                                                        redraw=True),
                                                        transition=dict(duration=500),
                                                        fromcurrent=True,
                                                        mode='immediate'
                                                       )
                                                  ]
                                            )
                                       ]
                              )
                         ],
             sliders=sliders);

# Plot the figure 
fig=go.Figure(data=data, layout=layout, frames=frames)
import plotly.io as pio
pio.renderers.default = "browser"  ##offline plot
fig.show()

Any help or advice would be highly appreciated !

@Hi @lou80,

I made a few changes in your code starting from data definition.
A few remarks:

  • in frame definition we set only the properties that are changing with respect to the initial data. Hence in your case each frame updates only the z-list.
  • to activate the slider each frame has to have a name (it is a string)
  • in args sliders definition you should give the frame name, not the frame itself, as you did.

Here is the code to replace your one, starting from data definition:

data = [go.Choroplethmapbox(locations = [jdata['features'][k]['id'] for k in range(L)],
                             z = np.random.randint(-10, 10,  size=L),
                             colorscale = 'deep',
                             text =regions, 
                             zmin=-10,
                             zmax = 10,
                             colorbar = dict(thickness=20, ticklen=3),
                             geojson = jdata,
                             marker_line_width=0, marker_opacity=0.7)]


date_range = ['2014', '2015', '2016', '2017', '2018']
frames = []

for N, q in enumerate(date_range):
    frames.append(go.Frame(data=[go.Choroplethmapbox(
                                 z = np.random.randint(-10, 10,  size=L))],
                          name=f'frame{N+1}')
                  )

sliders = [dict(steps= [dict(method= 'animate',
                       args= [[f'frame{k+1}'],
                              dict(mode= 'immediate',
                              frame= dict( duration=600, redraw= True ),
                                       transition=dict( duration= 200)
                                      )
                                ],
                        label='Date : {}'.format(date_range[k])
                         ) for k in range(0,len(frames))], 
            transition= dict(duration= 100 ),
            x=0,
            y=0,
            currentvalue=dict(font=dict(size=12), visible=True, xanchor= 'center'),
            len=1.0)
       ]

# Update Layout
layout.update(updatemenus=[dict(type='buttons', showactive=False,
                               y=0,
                               x=0,
                               xanchor='left',
                               pad=dict(t=5, r=10),
                               buttons=[dict(label='Play',
                                             method='animate',
                                             args=[None, 
                                                   dict(frame=dict(duration=600, 
                                                        redraw=True),
                                                        transition=dict(duration=200),
                                                        fromcurrent=True,
                                                        mode='immediate'
                                                       )
                                                  ]
                                            )
                                       ]
                              )
                         ],
             sliders=sliders);

# Plot the figure 
fig=go.Figure(data=data, layout=layout, frames=frames)
fig.show('browser')
1 Like

Awesome ! Thank you !