Остановка / запуск / пауза в анимации Python Matplotlib
Я использую FuncAnimation в модуле анимации matplotlib для некоторой базовой анимации. Эта функция постоянно проходит через анимацию. Есть ли способ, с помощью которого я могу приостановить и перезапустить анимацию, скажем, щелчком мыши?
5 ответов
Вот пример FuncAnimation, который я изменил, чтобы приостановить щелчки мышью. Поскольку анимация управляется функцией генератора, simData
когда глобальная переменная pause
Истинно, получение тех же данных делает анимацию приостановленной.
Значение 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)
plt.show()
Это работает...
anim = animation.FuncAnimation(fig, animfunc[,..other args])
#pause
anim.event_source.stop()
#unpause
anim.event_source.start()
Комбинируя здесь ответы от @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()
Теперь мы можем просто остановить или запустить анимацию с помощью кликов.
Я попал на эту страницу, пытаясь реализовать ту же функциональность, останавливая анимацию 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()
Некоторые заметки:
- Чтобы иметь возможность изменять значения
running
а такжеdirection
Я назначил ихanim
, Он избегает использования нелокальных (недоступно в Python2.7) или глобальных (не желательно, так как я запускаю этот код в другой функции). Не уверен, что это хорошая практика, но я нашел это довольно элегантно. - Для обновления вручную я обращаюсь
anim
объект генератора, который FuncAnimation использует для обновления графика. Это гарантирует, что когда я возобновляю анимацию, она начинается с активного кадра, а не с того места, где она была изначально приостановлена.
Поскольку есть довольно много комментариев к разным ответам с просьбой о документированной функции, я копнул глубже, основываясь на ответе Фреда . Вроде работает, но начиная с matplotlib 3.4.0 появились новые функции для приостановки и возобновления построения: pause()
а также resume()
. Они звонят
event_source.stop()
а также
start()
внутренне, но они также полностью приостанавливают анимацию, что может снизить нагрузку на оборудование.
Их можно вызвать в любой
matplotlib.animation.Animation
объект, в том числе
FuncAnimation
подкласс.