I have searched for proper animation script and come up with following function on how to add traces:
from plotly import graph_objects as go
def add_anim_frames(figure: go.Figure, traces):
sliders_dict = {
"active": 0,
# "yanchor": "top",
# "xanchor": "left",
"currentvalue": {
"font": {"size": 20},
"prefix": "",
"visible": True,
"xanchor": "right"
},
"transition": {"duration": 300, "easing": "cubic-in-out"},
"len": 0.9,
# "x": 0.1,
# "y": 0,
"steps": [],
'pad': dict(zip('lrtb', [0, 0, 0, 0])),
}
frames = [
go.Frame(data=trace_list,
traces=list(range(len(trace_list))),
name=str(i))
for i, trace_list in enumerate(traces)
]
f_debug = frames[0]
print(len(f_debug.data))
print(f_debug.traces)
sliders_dict['steps'] = [
{"args": [[fr.name],
{"frame": {"duration": 0, "redraw": True},
"mode": "immediate",
"transition": {"duration": 0}}],
"label": i,
"method": "animate"} for i, fr in enumerate(frames)]
figure.frames = frames
figure.layout.updatemenus = [
go.layout.Updatemenu(
type='buttons',
buttons=[
go.layout.updatemenu.Button(
label="Play",
method="animate",
args=[
None,
{'frame': {"duration": 50, "redraw": True},
"mode": "immediate",
"fromcurrent": True,
"transition": {"duration": 50, "easing": "linear"}},
]),
go.layout.updatemenu.Button(
label='Pause',
method='animate',
args=[
[None],
{"frame": {"duration": 0, "redraw": False},
"mode": "immediate",
"transition": {"duration": 0}}
]),
],
bgcolor='rgba(0, 0, 0, 0)', active=99, bordercolor='black',
font=dict(size=11, color='white', ), showactive=False,
**{
"direction": "right",
'pad': dict(zip('lrtb', [0, 0, 0, 0])),
"x": 0.5,
"xanchor": "right",
"y": 1,
"yanchor": "top"
}
),
]
figure.layout.sliders = [sliders_dict]
And i display my figure like this:
import numpy as np
from plotly import graph_objects as go
cube_points = np.zeros((8, 3))
cube_points[[2, 3, 4, 5], 0] = 1
cube_points[[1, 2, 5, 6], 1] = 1
cube_points[[4, 5, 6, 7], 2] = 1
N_FRAMES = 40
anim_points = np.stack([
np.sin(np.arange(N_FRAMES)),
np.cos(np.arange(N_FRAMES)),
np.arange(N_FRAMES)/10
], axis=-1)
static_traces = [
go.Scatter3d(**dict(zip('xyz', cube_points.T*5)), mode='markers', name='static'),
]
anim_traces = [
[
go.Scatter3d(**dict(zip('xyz', anim_points[[i-1, i, i+1]].T + 2.5)), mode='lines', marker_color='lime'),
go.Scatter3d(**dict(zip('xyz', anim_points[[i-1, i, i+1]].T + 2.7)), mode='lines', marker_color='olive'),
go.Scatter3d(**dict(zip('xyz', anim_points[[i-1, i, i+1]].T+2.3)), mode='lines', marker_color='blue'),
]
for i in range(1, N_FRAMES-1)]
fig = go.Figure(data=[go.Scatter3d()])
fig.add_traces(static_traces)
fig.update_layout(plt.get_layout_3d(show_grid=True), height=700)
add_anim_frames(fig, anim_traces)
fig.show()
Problem is that it seems that Frame
object is capable of displaying only 2 traces at once:
If i leave only 1 trace in anim traces list, static trace will be shown, if i will add extra enim trace, only anim traces will be shown and if i add even more, only first 2 anim traces will be shown. Please help