I'm using FuncAnimation in matplotlib's animation module for some basic animation. This function perpetually loops through the animation. Is there a way by which I can pause and restart the animation by, say, mouse clicks?
5 Answers
Here is a FuncAnimation example which I modified to pause on mouse clicks.
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.
The value of paused
is toggled by setting up an event callback:
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()
-
Cute, handy, entertaining, and in a way, nostalgic; https://youtu.be/TxmZ5sabk7U?t=17 or https://youtu.be/C1HuX6nQnQY?t=211 – uhoh Oct 26 '17 at 05:45
-
@unutbu It does not work for me. The window is closed quickly. My platform: Windows 10, python 3.8, matplotlib 3.4.2. – user153245 Oct 05 '21 at 16:36
This works...
anim = animation.FuncAnimation(fig, animfunc[,..other args])
#pause
anim.event_source.stop()
#unpause
anim.event_source.start()

- 243
- 2
- 3
Combining both the answers from @fred and @unutbu here, we can add an onClick function after creating the animation:
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.

- 2,031
- 1
- 18
- 33

- 325
- 2
- 7
-
What version of matplotlib are you running? This doesn't seem to work for me – bretcj7 Jun 15 '17 at 03:47
-
@bretcj7 I'm using version 1.5.3. Sorry, should have mentioned that! – woodenflute Jun 19 '17 at 15:51
-
2I can't seem to find the documentation on matplotlib for the event_source.stop() or start? Does it exist? – bretcj7 Jun 27 '17 at 12:18
-
1You need to assign the function to the event also, `fig.canvas.mpl_connect('button_press_event', onClick)` and I guess replace `nonlocal` with `global` – Jens Munk Aug 21 '17 at 18:04
I landed on this page trying to implement the same functionality, pausing matplotlibs animation. 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
anddirection
, I assigned them toanim
. It avoids using nonlocal (not avaible in Python2.7) or global (not desirable since I'm running this code within another function). 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. This ensures that when I resume the animation, it starts from the active frame rather than from where it was originally paused.

- 2,899
- 4
- 15
- 24
-
Where are `.running` and `.direction` documented? I'm wondering if `event_source.start()` is "less" undocumented feature. – Shital Shah Jan 15 '19 at 01:46
-
`.running` and `.direction` are not documented, I made that up myself. See e.g. [this](http://blog.lerner.co.il/python-attributes/) blog post: you can just assign new attributes to any object and it will probably work just fine. Not sure whether this is good practice, but I found it quite useful here. I'm not sure whether `event_source.start()` is documented, but I think I found it in the source code or in another SO post. – Peter9192 Jan 18 '19 at 16:37
-
As soon as i press left or right key I get following error: t = anim.frame_seq.next() AttributeError: 'generator' object has no attribute 'next' – Gino Gulamhussene Nov 05 '19 at 10:18
-
@Gino Gulamhussene I bet you are using python3 :-)... change t = anim.frame_seq.next() to t = anim.frame_seq.__next__(). – David Daverio Apr 04 '21 at 21:04
-
Very elegant! I just modified a bit the generator. As it was values of t could become negative... ok will do it later... lol edit queue look to be full thanks to a missclick! – David Daverio Apr 05 '21 at 03:18
-
How to make this work with blit=true (see my [follow up question](https://stackoverflow.com/questions/70145156/step-forward-and-backward-frame-by-frame-in-animation-in-matplolib-problem-when]) – student Nov 28 '21 at 16:09
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()
. They call event_source.stop()
and start()
internally, but they also pause animation altogether, which may reduce the hardware strain.
They can be called on any matplotlib.animation.Animation
object, including FuncAnimation
subclass.

- 18,008
- 2
- 24
- 52