@Bijan Please change the title of your question as: “How to simultaneously animate multiple traces of the same Figure”.
As I stressed in my previous answers related to this topic, I repeat it here again:
- First, defines a go.Figure, and add your traces; Let us say fig.data[0], Fig.data[1], …
- Within go.Frame definition we set only the attributes in fig.data[k] trace that change from frame to frame. Don’t repeat the fixed attributes here!
- to let plotly.js know what trace is updated by each
go.Frame.data[k]
, insert in go.Frame definition the line
traces=[0,1,..]
.
- each frame has a name, to be used in
sliders
definition in order to connect that frame with a slider step.
Below is an example with two traces. Each frame updates the z
-values, and the line_color
in the trace fig.data[0],
respectively the marker_symbol
in fig.data[1]
.
import plotly.graph_objects as go
import numpy as np
#from plotly.offline import iplot
def rndata():
return np.random.randint(1,10,10)
n_frames=10
my_colors = ["RoyalBlue", "#09ffff", "#19d3f3", "#e763fa", "#ab63fa",
"#636efa", "#00cc96", "#EF553B", "#119DFF", "#0D76BF" ]
my_symbols= ['circle', 'circle-open', 'cross', 'diamond',
'diamond-open', 'square', 'square-open', 'x', 'circle', 'diamond']
fig = go.Figure(go.Scatter3d(x=rndata(),y=rndata(),z=rndata(), name='Nodes1', mode="lines",
line_color="RoyalBlue", line_width=2
))
fig.add_scatter3d(x=rndata(),y=rndata(),z=rndata(),
mode="markers", marker_symbol=["circle"]*10,
name='Nodes2', marker_size=6)
frames = []
for k in range(n_frames):
frames.append(go.Frame(data=[go.Scatter3d(z=rndata(), line_color=my_colors[k]),
go.Scatter3d(marker_symbol=[my_symbols[k]]*10)],
traces=[0,1], #This means that the above trace updates (within go.Frame definition)
#are performed for fig.data[0], fig.data[1]
name=f"fr{k}"))
fig.update(frames=frames)
updatemenus = [dict(
buttons = [
dict(
args = [None, {"frame": {"duration": 500, "redraw": True},
"fromcurrent": True}],
label = "Play",
method = "animate"
),
dict(
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(steps = [dict(method= 'animate',
args= [[f'frame{k}'],
dict(mode= 'immediate',
frame= dict(duration=400, redraw=True),
transition=dict(duration= 0))
],
label=f'{k+1}'
) for k in range(n_frames)],
active=0,
transition= dict(duration= 0 ),
x=0, # slider starting position
y=0,
currentvalue=dict(font=dict(size=12),
prefix='frame: ',
visible=True,
xanchor= 'center'
),
len=1.0) #slider length
]
fig.update_layout(width=600, height=600,
updatemenus=updatemenus,
sliders=sliders)
fig.show()