You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止基于FuncAnimation子类Player创建的动画自动启动?

解决方案

要让动画初始化后不自动启动,只需要对Player类做两处关键修改:

  1. 修改初始运行状态,将self.runs的初始值从True改为False
  2. 在调用父类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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 21:30:31