如何阻止基于FuncAnimation子类Player创建的动画自动启动?
解决方案
要让动画初始化后不自动启动,只需要对Player类做两处关键修改:
- 修改初始运行状态,将
self.runs的初始值从True改为False - 在调用父类
FuncAnimation的初始化方法时,添加autostart=False参数,禁止matplotlib自动启动动画
修改后的完整代码
import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from mpl_toolkits.axes_grid1 import make_axes_locatable import mpl_toolkits import matplotlib.widgets from matplotlib.figure import Figure class Player(FuncAnimation): def __init__(self, fig, func, frames=None, init_func=None, fargs=None,save_count=None, mini=0, maxi=100, pos=(0.125, 0.92), **kwargs): self.i = 0 self.min=mini self.max=maxi self.runs = False # 修改初始运行状态为关闭 self.forwards = True self.fig = fig self.func = func self.setup(pos) # 添加autostart=False参数,禁止matplotlib自动启动动画 FuncAnimation.__init__(self,self.fig, self.func, frames=self.play(), init_func=init_func, fargs=fargs, save_count=save_count,interval=500, autostart=False, **kwargs ) def play(self): while self.runs: self.i = self.i+self.forwards-(not self.forwards) if self.i > self.min and self.i < self.max: yield self.i else: self.stop() yield self.i def start(self): if self.i==self.max: self.i=0 self.runs=True self.event_source.start() def stop(self, event=None): self.runs = False self.event_source.stop() def forward(self, event=None): self.forwards = True self.start() def backward(self, event=None): self.forwards = False self.start() def oneforward(self, event=None): if self.i==self.max: self.i=0 self.forwards = True self.onestep() def onebackward(self, event=None): self.forwards = False self.onestep() def onestep(self): if self.i > self.min and self.i < self.max: self.i = self.i+self.forwards-(not self.forwards) elif self.i == self.min and self.forwards: self.i+=1 elif self.i == self.max and not self.forwards: self.i-=1 self.func(self.i) self.fig.canvas.draw_idle() def setup(self, pos): playerax = self.fig.add_axes([0.4, 0.92, 0.22, 0.03]) divider = mpl_toolkits.axes_grid1.make_axes_locatable(playerax) bax = divider.append_axes("right", size="80%", pad=0.05) sax = divider.append_axes("right", size="80%", pad=0.05) fax = divider.append_axes("right", size="80%", pad=0.05) ofax = divider.append_axes("right", size="100%", pad=0.05) self.button_oneback = matplotlib.widgets.Button(playerax , label=u'$\u29CF$') self.button_back = matplotlib.widgets.Button(bax, label=u'$\u25C0$') self.button_stop = matplotlib.widgets.Button(sax, label=u'$\u25A0$') self.button_forward = matplotlib.widgets.Button(fax, label=u'$\u25B6$') self.button_oneforward = matplotlib.widgets.Button(ofax, label=u'$\u29D0$') self.button_oneback.on_clicked(self.onebackward) self.button_back.on_clicked(self.backward) self.button_stop.on_clicked(self.stop) self.button_forward.on_clicked(self.forward) self.button_oneforward.on_clicked(self.oneforward) ######## EXAMPLE ################## ####################################### fig, ax = plt.subplots() t=np.linspace(0,1, num=100) unit_circle_x=np.cos(2*np.pi*t) unit_circle_y=np.sin(2*np.pi*t) ax.plot(unit_circle_x,unit_circle_y) ax.set_xlim(-1.2, 1.2) ax.set_ylim(-1.2,1.2) # arrow tracing out unit circle n=3 unit_vector_x=np.cos(2*np.pi*n*t) unit_vector_y=np.sin(2*np.pi*n*t) unit_circle_vector=ax.quiver(0, 0, unit_vector_x[0], unit_vector_y[0], angles='xy', scale_units='xy', scale=1,headwidth=10) ax.set_aspect("equal") def update(i): unit_circle_vector.set_UVC(unit_vector_x[i],unit_vector_y[i]) ax.set_xlabel(r'$i= $'+str(i),rotation=0,labelpad=10) ani = Player(fig, update, maxi=len(t)-1) plt.show()
修改说明
self.runs = False:初始状态下关闭动画的循环播放逻辑,play()生成器不会持续生成帧autostart=False:禁用FuncAnimation的自动启动特性,确保matplotlib底层不会主动触发动画播放
修改后,程序运行后会停留在初始帧(i=0),只有点击播放按钮(▶)才会开始动画,点击其他控制按钮也能正常逐帧或反向播放。
内容的提问来源于stack exchange,提问作者fishbacp
相关产品推荐
相关产品推荐

