【发布时间】:2022-11-11 18:11:26
【问题描述】:
我正在尝试使用 Plotly 和 Dash 创建一个动画仪表。我已经设法通过一个简单的饼图来做到这一点,该饼图带有一个从零开始旋转到给定值的针形。
我面临的问题是我使用框架添加了针的动画。这些帧当前链接到播放按钮,动画仅在单击按钮时起作用。我想在情节(页面)加载后立即自动播放动画 - 即完全摆脱播放按钮。
我发现了一些建议 dcc.Interval 相同的参考资料,但我无法弄清楚如何做到这一点。任何帮助和建议都会非常有帮助。谢谢。
这是我的与播放按钮一起使用的动画仪表的代码。
import numpy as np
import plotly.express as px
import plotly.io as pio
import plotly.offline as ofl
import plotly.graph_objects as go
import plotly.colors as pc
import dash
from dash import dcc
from dash import html
def createGaugePlot(gaugeValue=20):
# Creating the Pie plot object using the labels and values
pieTrace = go.Pie(
name="Gauge",
labels=["A", "B", "C", "D", "E"],
values=[20, 20, 20, 20, 20],
marker=dict(colors=["#0d0887", "#46039f", "#7201a8", "#9c179e", "#bd3786"], line=dict(color="rgba(0,0,0,0)")),
hole=0.5,
direction="clockwise",
hoverinfo="none",
textinfo="none",
sort=False,
showlegend=False,
)
shapeDefaults = dict(
line_color="#888888",
fillcolor="#888888",
xsizemode="scaled",
ysizemode="scaled",
xref="x domain",
yref="y domain",
)
needlePath = computeNeedlePath(gaugeValue=0)
needleShape = dict(
type="path",
path=needlePath,
line=dict(width=0),
)
circleShape = dict(
type="circle",
x0=0.47,
y0=0.47,
x1=0.53,
y1=0.53,
)
layoutShapes = dict(
shapes=[needleShape | shapeDefaults, circleShape | shapeDefaults]
)
animationFrames = []
for v in range(gaugeValue):
needlePath = computeNeedlePath(gaugeValue=v)
animationFrames.append(
go.Frame(
layout=dict(
shapes=[dict(type="path", path=needlePath)],
)
)
)
frameSpeedOptions = dict(frame=dict(duration=10), transition=dict(duration=10))
playButton = dict(
updatemenus=[
dict(
type="buttons",
buttons=[
dict(
label="Play",
method="animate",
args=[animationFrames, frameSpeedOptions],
)
],
x=-0.2,
y=1,
xanchor="left",
yanchor="top",
)
]
)
fig = go.Figure(
data=[pieTrace],
layout=layoutShapes | playButton,
frames=animationFrames,
)
fig.update_layout(
autosize=False,
width=360,
height=360,
)
return fig
def computeNeedlePath(
gaugeValue: int,
needleWidth: float = 0.06,
needleHeight: float = 0.37,
needleOriginX: float = 0.5,
needleOriginY: float = 0.5,
) -> str:
gaugeRatio = (2 * gaugeValue - 100) / (2 * 100)
theta = np.radians(-360 * gaugeRatio)
origin = dict(x=needleOriginX, y=needleOriginY)
point1 = dict(x=origin["x"] - needleWidth / 2, y=origin["y"])
point2 = dict(x=origin["x"] + needleWidth / 2, y=origin["y"])
point3 = dict(x=origin["x"], y=origin["y"] + needleHeight)
newPoint1 = rotatePoint(point1, origin, theta)
newPoint2 = rotatePoint(point2, origin, theta)
newPoint3 = rotatePoint(point3, origin, theta)
needlePath = f"M{newPoint1['x']},{newPoint1['y']} L{newPoint2['x']},{newPoint2['y']} L{newPoint3['x']},{newPoint3['y']} Z"
return needlePath
def rotatePoint(point: dict, origin: dict, theta: float) -> dict:
return dict(
x=round(
np.cos(theta) * (point["x"] - origin["x"])
- np.sin(theta) * (point["y"] - origin["y"])
+ origin["x"],
6,
),
y=round(
np.sin(theta) * (point["x"] - origin["x"])
+ np.cos(theta) * (point["y"] - origin["y"])
+ origin["y"],
6,
),
)
app = dash.Dash(__name__)
app.layout = html.Div(
children=[
html.H1(
children="Gauge plot",
),
html.P(
children="Animated gauge plot with rotating needle",
),
dcc.Graph(
figure=createGaugePlot(gaugeValue=100),
animate=True,
animation_options=dict(frame=dict(redraw=True), transition=dict(duration=10)),
config=dict(displayModeBar=False),
),
]
)
app.run_server(debug=True)
【问题讨论】:
标签: python plotly plotly-dash