简体   繁体   English

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

[英]stop / start / pause in python matplotlib animation

I'm using FuncAnimation in matplotlib's animation module for some basic animation.我在 matplotlib 的动画模块中使用 FuncAnimation 来制作一些基本动画。 This function perpetually loops through the animation.这个函数永远循环播放动画。 Is there a way by which I can pause and restart the animation by, say, mouse clicks?有没有一种方法可以让我通过鼠标点击来暂停和重新启动动画?

"

Here is a FuncAnimation example which I modified to pause on mouse clicks.这是一个 FuncAnimation 示例,我将其修改为在鼠标点击时暂停。 Since the animation is driven by a generator function, simData , when the global variable pause is True, yielding the same data makes the animation appear paused.由于动画是由生成器函数simData驱动的,当全局变量pause为 True 时,产生相同的数据会使动画看起来暂停。

The value of paused is toggled by setting up an event callback: 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()

This works...这工作...

anim = animation.FuncAnimation(fig, animfunc[,..other args])

#pause
anim.event_source.stop()

#unpause
anim.event_source.start()

Combining both the answers from @fred and @unutbu here, we can add an onClick function after creating the animation:在这里结合@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()

Now we can simply stop or start the animation with clicks.现在我们可以简单地通过点击停止或开始动画。

I landed on this page trying to implement the same functionality, pausing matplotlibs animation.我登陆这个页面试图实现相同的功能,暂停 matplotlibs 动画。 The other answers are great, but in addition I wanted to be able to manually loop through the frames using the arrow keys.其他答案很好,但除此之外,我还希望能够使用箭头键手动循环浏览帧。 For anyone looking for the same functionality, here's my implementation:对于任何寻找相同功能的人,这是我的实现:

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()

Some notes:一些注意事项:

  • To be able to modify the values of running and direction , I assigned them to anim .为了能够修改runningdirection的值,我将它们分配给anim It avoids using nonlocal (not avaible in Python2.7) or global (not desirable since I'm running this code within another function).它避免使用非本地(Python2.7 中不可用)或全局(不可取,因为我在另一个函数中运行此代码)。 Not sure whether this is good practice, but I found it quite elegant.不确定这是否是好的做法,但我发现它非常优雅。
  • For the manual update, I'm accessing anim 's generator object that FuncAnimation uses to update the plot.对于手动更新,我正在访问 FuncAnimation 用于更新绘图的anim的生成器对象。 This ensures that when I resume the animation, it starts from the active frame rather than from where it was originally paused.这确保当我恢复动画时,它从活动帧开始,而不是从最初暂停的位置开始。

Since there are quite a few comments on different answers asking for documented feature, I dug deeper based on fred's answer .由于有很多关于不同答案要求记录功能的评论,我根据弗雷德的回答进行了更深入的挖掘。 It seems to work, but since matplotlib 3.4.0 there are new functions to pause and resume plotting: pause() and resume() .它似乎有效,但自 matplotlib 3.4.0 以来,有新的函数可以暂停和恢复绘图: pause()resume() They call event_source.stop() and start() internally, but they also pause animation altogether, which may reduce the hardware strain.它们在内部调用event_source.stop()start() ,但它们也完全暂停动画,这可能会减少硬件压力。

They can be called on any matplotlib.animation.Animation object, including FuncAnimation subclass.它们可以在任何matplotlib.animation.Animation对象上调用,包括FuncAnimation子类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM