在 matplotlib 动画中停止/开始/暂停
- 2025-03-21 09:07:00
- admin 原创
- 65
问题描述:
我正在使用 matplotlib 动画模块中的 FuncAnimation 来制作一些基本动画。此函数会永久循环播放动画。有没有办法可以通过鼠标单击等方式暂停和重新启动动画?
解决方案 1:
下面是一个 FuncAnimation 示例,我对其进行了修改,使其在鼠标单击时暂停。由于动画由生成器函数驱动,simData
因此当全局变量pause
为 True 时,产生相同的数据会使动画看起来暂停了。
paused
通过设置事件回调来切换的值:
def onClick(event):
global pause
pause ^= True
fig.canvas.mpl_connect('button_press_event', onClick)
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
pause = False
def simData():
t_max = 10.0
dt = 0.05
x = 0.0
t = 0.0
while t < t_max:
if not pause:
x = np.sin(np.pi*t)
t = t + dt
yield x, t
def onClick(event):
global pause
pause ^= True
def simPoints(simData):
x, t = simData[0], simData[1]
time_text.set_text(time_template%(t))
line.set_data(t, x)
return line, time_text
fig = plt.figure()
ax = fig.add_subplot(111)
line, = ax.plot([], [], 'bo', ms=10)
ax.set_ylim(-1, 1)
ax.set_xlim(0, 10)
time_template = 'Time = %.1f s'
time_text = ax.text(0.05, 0.9, '', transform=ax.transAxes)
fig.canvas.mpl_connect('button_press_event', onClick)
ani = animation.FuncAnimation(fig, simPoints, simData, blit=False, interval=10,
repeat=True)
fig.show()
解决方案 2:
这有效...
anim = animation.FuncAnimation(fig, animfunc[,..other args])
#pause
anim.event_source.stop()
#unpause
anim.event_source.start()
解决方案 3:
结合@fred 和@unutbu 的答案,我们可以在创建动画后添加一个 onClick 函数:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
def run_animation():
anim_running = True
def onClick(event):
nonlocal anim_running
if anim_running:
anim.event_source.stop()
anim_running = False
else:
anim.event_source.start()
anim_running = True
def animFunc( ...args... ):
# Animation update function here
fig.canvas.mpl_connect('button_press_event', onClick)
anim = animation.FuncAnimation(fig, animFunc[,...other args])
run_animation()
现在我们只需点击一下就可以停止或开始动画。
解决方案 4:
我来到这个页面,试图实现相同的功能,暂停 matplotlibs 动画。其他答案都很棒,但此外,我希望能够使用箭头键手动循环遍历帧。对于任何寻找相同功能的人,这是我的实现:
import matplotlib.pyplot as plt
import matplotlib.animation as ani
fig, ax = plt.subplots()
txt = fig.text(0.5,0.5,'0')
def update_time():
t = 0
t_max = 10
while t<t_max:
t += anim.direction
yield t
def update_plot(t):
txt.set_text('%s'%t)
return txt
def on_press(event):
if event.key.isspace():
if anim.running:
anim.event_source.stop()
else:
anim.event_source.start()
anim.running ^= True
elif event.key == 'left':
anim.direction = -1
elif event.key == 'right':
anim.direction = +1
# Manually update the plot
if event.key in ['left','right']:
t = anim.frame_seq.next()
update_plot(t)
plt.draw()
fig.canvas.mpl_connect('key_press_event', on_press)
anim = ani.FuncAnimation(fig, update_plot, frames=update_time,
interval=1000, repeat=True)
anim.running = True
anim.direction = +1
plt.show()
一些说明:
为了能够修改
running
和的值direction
,我将它们赋值给anim
。这样可以避免使用非本地(在 Python2.7 中不可用)或全局(由于我在另一个函数中运行此代码,因此不可取)。不确定这是否是好的做法,但我发现它非常优雅。对于手动更新,我正在访问
anim
FuncAnimation 用于更新绘图的生成器对象。这确保当我恢复动画时,它从活动帧开始,而不是从最初暂停的位置开始。
解决方案 5:
由于对不同答案的评论中有很多要求记录功能的评论,因此我根据fred 的回答进行了更深入的研究。它似乎有效,但自 matplotlib 3.4.0 以来,有新功能可以暂停和恢复绘图:pause()
和resume()
。它们在内部调用event_source.stop()
和start()
,但它们也会完全暂停动画,这可能会减轻硬件压力。
它们可以在任何对象上调用matplotlib.animation.Animation
,包括FuncAnimation
子类。
扫码咨询,免费领取项目管理大礼包!