我试图使用plotly 生成动画3D 散点图,并将其显示在我使用Shiny (Python) Express 创建的仪表板上。当在 jupyter 笔记本上检查动画绘图的代码时 - 它工作得很好,但我无法让动画在 Shiny 上运行。
该图表是交互式的 - 即工具提示显示数据,但单击“播放”时没有动画。
import io
from pathlib import Path
from shiny import reactive
from shiny.express import input, ui, render
from shiny.types import FileInfo
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from shinywidgets import render_widget
import asyncio
ui.page_opts(
title="Visualisation",
fillable=True,
id="page",
)
with ui.card(full_screen=True):
@render_widget
def coordinate_space():
try:
with ui.Progress(min=1, max=5) as p:
data = {
'X': [1, 2, 3, 4, 5],
'Y': [5, 4, 3, 2, 1],
'Z': [2, 3, 4, 5, 6],
'FZ_new': [10, 20, 30, 40, 50],
'FZ': [5, 10, 15, 20, 25]
}
scaled_coordinate_system = pd.DataFrame(data)
p.set(2, message="Data loaded, preparing plot...")
fig = px.scatter_3d(scaled_coordinate_system, x='X', y='Y', z='Z',
size='FZ_new', color='FZ_new', opacity=0.7)
fig1 = go.Figure(fig)
p.set(3, message="Adding traces to the plot...")
frames = [
go.Frame(data=[go.Scatter3d(
x=scaled_coordinate_system['X'],
y=scaled_coordinate_system['Y'],
z=scaled_coordinate_system['Z'],
mode='markers',
marker=dict(size=scaled_coordinate_system['FZ_new'] * 10, color="Red"),
opacity=0.9,
name='Frame 1',
)]),
go.Frame(data=[go.Scatter3d(
x=scaled_coordinate_system['X'],
y=scaled_coordinate_system['Y'],
z=scaled_coordinate_system['Z'],
mode='markers',
marker=dict(size=scaled_coordinate_system['FZ'], color=scaled_coordinate_system['FZ']),
opacity=0.7,
name='Frame 2'
)])
]
print("Frames")
fig1.frames = frames
p.set(4, message="Updating layout...")
fig1.update_layout(
scene=dict(
xaxis_title='X AXIS',
yaxis_title='Y AXIS',
zaxis_title='Z AXIS'
),
updatemenus=[dict(
type='buttons',
direction = "down",
showactive=True,
buttons=[
dict(
label='Play',
method='animate',
args=[None, dict(
frame=dict(duration=500, redraw=True),
fromcurrent=True,
transition=dict(duration=0)
)]
),
dict(
label='Pause',
method='animate',
args=[[None], dict(
frame=dict(duration=0, redraw=False),
mode='immediate'
)]
)
]
)]
)
fig1.update_layout(margin=dict(l=0, r=0, b=0, t=0))
camera = dict(
eye=dict(x=2, y=2, z=0.5)
)
fig1.update_layout(scene_camera=camera)
p.set(5, message="Rendering plot...")
return fig1
except Exception as e:
ui.notification_show(f"{e}", duration=20, type="error")
return None
上面是我的渲染绘图函数的代码。我在想动画渲染问题是否与异步函数有关,所以我将其更改为同步。我不知道该怎么办。
编辑:我的动画仅影响散点图中标记的大小。
有人可以帮我吗?
要渲染绘图,只需按如下所示更改这两行:
(1)
@render_widget
-> @render.ui
return fig1
-> return ui.HTML(fig1.to_html())
它会起作用的。如果您想知道为什么它不适用于
@render_widget
,那是因为它隐式地将 go.Figure()
转换为 go.FigureWidget()
并且 go.FigureWidget()
不支持 frames
。因此,解决方法是在 HTML 标记内渲染。