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

继承FuncAnimation的动画播放器末尾重放索引越界问题如何解决

问题根源

原代码在动画播放到首尾边界时仅停止了播放进程,没有重置当前帧索引self.i的状态,再次点击播放按钮时,索引会超出设定的min/max范围,调用更新函数时就会触发数组索引越界错误。

优化方案(推荐:播放结束后点击自动从头重播)

仅需修改forward、backward两个方法,同时补全原示例缺失的numpy导入即可,完整可运行代码如下:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import mpl_toolkits.axes_grid1
import matplotlib.widgets

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, **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):
        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
        # 新增:如果已经到最大帧,重置到开头
        if self.i >= self.max:
            self.i = self.min
        self.start()
    def backward(self, event=None):
        self.forwards = False
        # 新增:如果已经到最小帧,重置到末尾
        if self.i <= self.min:
            self.i = self.max
        self.start()
    def oneforward(self, event=None):
        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([pos[0],pos[1], 0.22, 0.04])
        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'$⧏$')
        self.button_back = matplotlib.widgets.Button(bax, label=u'$◀$')
        self.button_stop = matplotlib.widgets.Button(sax, label=u'$■$')
        self.button_forward = matplotlib.widgets.Button(fax, label=u'$▶$')
        self.button_oneforward = matplotlib.widgets.Button(ofax, label=u'$⧐$')
        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)

### 使用方式和FuncAnimation完全一致

fig, ax = plt.subplots()
x = np.linspace(0,6*np.pi, num=100)
y = np.sin(x)

ax.plot(x,y)
point, = ax.plot([],[], marker="o", color="crimson", ms=15)

def update(i):
    point.set_data(x[i],y[i])

ani = Player(fig, update, maxi=len(y)-1)

plt.show()

可选方案(播放结束后点击播放无响应)

如果不需要重播效果,只需要避免报错,将上面forward和backward方法的逻辑替换为边界判断即可:

def forward(self, event=None):
    self.forwards = True
    # 只有还没到最大帧才启动播放
    if self.i < self.max:
        self.start()
def backward(self, event=None):
    self.forwards = False
    # 只有还没到最小帧才启动播放
    if self.i > self.min:
        self.start()

内容的提问来源于stack exchange,提问作者fishbacp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:15:00