python matplotlib动画中的停止/开始/暂停

Posted

技术标签:

【中文标题】python matplotlib动画中的停止/开始/暂停【英文标题】:stop / start / pause in python matplotlib animation 【发布时间】:2013-05-19 21:39:01 【问题描述】:

我在 matplotlib 的动画模块中使用 FuncAnimation 来制作一些基本动画。这个函数永远循环播放动画。有没有一种方法可以让我通过鼠标点击来暂停和重新启动动画?

【问题讨论】:

【参考方案1】:

这是a FuncAnimation example,我将其修改为在鼠标点击时暂停。 由于动画是由生成器函数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()

【讨论】:

可爱、方便、有趣,而且在某种程度上还很怀旧; youtu.be/TxmZ5sabk7U?t=17 或 youtu.be/C1HuX6nQnQY?t=211 @unutbu 这对我不起作用。窗户很快就关上了。我的平台:Windows 10、python 3.8、matplotlib 3.4.2。【参考方案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()

现在我们可以通过点击简单地停止或启动动画。

【讨论】:

你运行的是什么版本的 matplotlib?这似乎对我不起作用 @bretcj7 我使用的是 1.5.3 版。对不起,应该提到的! 我似乎在 matplotlib 上找不到 event_source.stop() 或 start 的文档?它存在吗? 您还需要将函数分配给事件,fig.canvas.mpl_connect('button_press_event', onClick),我想将 nonlocal 替换为 global【参考方案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()

一些注意事项:

为了能够修改runningdirection 的值,我将它们分配给anim。它避免使用非本地(在 Python2.7 中不可用)或全局(不可取,因为我在另一个函数中运行此代码)。不确定这是否是好的做法,但我发现它非常优雅。 对于手动更新,我正在访问 anim 的生成器对象,FuncAnimation 使用它来更新绘图。这可确保当我恢复动画时,它会从活动帧开始,而不是从最初暂停的位置开始。

【讨论】:

.running.direction 记录在哪里?我想知道event_source.start() 是否是“少”的未记录功能。 .running.direction 没有记录,这是我自己编造的。参见例如this 博客文章:您可以为任何对象分配新属性,它可能会正常工作。不确定这是否是好的做法,但我发现它在这里非常有用。我不确定event_source.start() 是否已记录在案,但我想我在源代码或另一篇 SO 帖子中找到了它。 当我按下左键或右键时,我得到以下错误:t = anim.frame_seq.next() AttributeError: 'generator' object has no attribute 'next' @Gino Gulamhussene 我打赌你正在使用 python3 :-)... 将 t = anim.frame_seq.next() 更改为 t = anim.frame_seq.__next__()。 非常优雅!我只是对生成器进行了一些修改。因为它的 t 值可能会变成负数...好的,稍后再做...大声笑编辑队列看起来已经满了,这要归功于一次missclick!

以上是关于python matplotlib动画中的停止/开始/暂停的主要内容,如果未能解决你的问题,请参考以下文章

Matplotlib,列表中的点动画

matplotlib 中的动画在 spyder 中不起作用

使用 Python Matplotlib 在 3D 轴上为振动传感器读数创建动画散点图

在 Python 中绘制动画箭袋

在 Python/Matplotlib 中动画“增长”线图

Matplotlib 动画图 - 图形在循环完成之前没有响应