matplotlib 如何防止使用作为FuncAnimation子类的Player类创建的动画自动启动?

carvr3hs  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(123)

我正在使用在matplotlib动画模块中管理动态绘图中找到的Player类来创建动画,但不知道如何修改初始值以防止动画自动启动。下面是Player的代码,沿着一个简单的示例,在该示例中,我绘制了单位圆,并在帧前进时用箭头跟踪单位圆:

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 = True
    self.forwards = True

    self.fig = fig
    self.func = func
    self.setup(pos)
    FuncAnimation.__init__(self,self.fig, self.func, frames=self.play(),
                                       init_func=init_func, fargs=fargs,
                                       save_count=save_count,interval=500, **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()
evrscar2

evrscar21#

您可以将self.runs变量初始化为False,并修改play方法,以便在self.runs=False

def play(self):
    while not self.runs:
        yield self.i
    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

请参阅下面的完整代码:

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)
        FuncAnimation.__init__(self,self.fig, self.func, frames=self.play(),
                                           init_func=init_func, fargs=fargs,
                                           save_count=save_count,interval=500, **kwargs )

    def play(self):
        while not self.runs:
            yield self.i
        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()

结果如下:

相关问题