Trying to build off of the example of building an animation from a dictionary here - Intro to Animations | Python | Plotly
Iโm trying to build a simple animation of a dot moving along a sine wave in preparation for developing a more complex animation, but I am having a hard time understanding some of the underlying mechanisms.
In the animation produced by the code below, the figure loads correctly (showing the sine wave defined in base_data_dict
)
However, when I click Play
, the dot animates correctly, but the background trace of the sine wave disappears. I have tried appending the base_data_dict
to the thisFrame
dictionary, but it still doesnโt work. I have tried reading the documentation, but I think there is something about the underlying mechanisms of Plotly that I am not understanding.
Any help would be appreciated, thank you!!
import numpy as np
import plotly.graph_objects as go
import dash
import dash_core_components as dcc
import dash_html_components as html
#%%
numFrames = 100
sinX = np.linspace(0,4*np.pi,numFrames)
sinY = np.sin(sinX)
xmin = np.min(sinX)
xmax = np.max(sinX)
ymin = np.min(sinY)
ymax = np.max(sinY)
#%%
# make figure
fig_dict = {
"data": [],
"layout": {},
"frames": []
}
# fill in most of layout
fig_dict["layout"]["xaxis"] = {"range": [xmin*1.1, xmax*1.1], "title": "This is the X axis title"}
fig_dict["layout"]["yaxis"] = {"range": [ymin*1.1, ymax*1.1],"title": "This is the Y axis title"}
fig_dict["layout"]["hovermode"] = "closest"
fig_dict["layout"]["updatemenus"] = [
{
"buttons": [
{
"args": [None, {"frame": {"duration": 0, "redraw": False},
"fromcurrent": True, "transition": {"duration": 0,
"easing": "linear"}}],
"label": "Play",
"method": "animate"
},
{
"args": [[None], {"frame": {"duration": 0, "redraw": False},
"mode": "immediate",
"transition": {"duration": 0}}],
"label": "Pause",
"method": "animate"
}
],
"direction": "left",
"pad": {"r": 10, "t": 87},
"showactive": False,
"type": "buttons",
"x": 0.1,
"xanchor": "right",
"y": 0,
"yanchor": "top"
}
]
sliders_dict = {
"active": 0,
"yanchor": "top",
"xanchor": "left",
"currentvalue": {
"font": {"size": 20},
"prefix": "Frame:",
"visible": True,
"xanchor": "right"
},
"transition": {"duration": 0, "easing": "linear"},
"pad": {"b": 10, "t": 50},
"len": 0.9,
"x": 0.1,
"y": 0,
"steps": []
}
#%% make data
base_data_dict = {
"x": sinX,
"y": sinY,
"mode": "lines+markers",
"marker": {
"size": 3
},
"name":'sine wave'
}
fig_dict["data"].append(base_data_dict)
#%% make frames
for fr in range(numFrames):
thisFrame = {"data": [], "name": str(fr)}
# thisFrame["data"].append(base_data_dict)
data_dict = {
"x": np.array(sinX[fr]),
"y": np.array(sinY[fr]),
"mode": "markers",
"text": 'thisFrameDotto',
"marker": {
"size": 5,
"color":"red"
},
"name": 'dotto'
}
thisFrame["data"].append(data_dict)
fig_dict["frames"].append(thisFrame)
slider_step = {"args": [
[fr],
{"frame": {"duration": 0, "redraw": False},
"mode": "immediate",
"transition": {"duration": 0}}
],
"label": fr,
"method": "animate"}
sliders_dict["steps"].append(slider_step)
fig_dict["layout"]["sliders"] = [sliders_dict]
fig = go.Figure(fig_dict)
#%% set up Dash/Plotly 'app server' to display figure
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
colors ={
'background': '#111111',
'text': '#7FDBFF'
}
#%% send figure data to Dash app server (I guess?!)
app.layout = html.Div(style={'backgroundColor':colors['background']},
children=[
html.H1(
children='Big Title',
style={
'textAlign':'center',
'color':colors['text']
}
),
html.Div(
children='Little Title.',
style={
'textAlign': 'center',
'color': colors['text']
}
),
dcc.Graph(
id='example-graph',
figure=fig
)
])
# %% actually run the server app
if __name__ == '__main__':
print('Figure displayed at http://127.0.0.1:8050/')
app.run_server(debug=True)