I recently needed to overlay a Matplotlib animation on an image in a keynote presentation. This requires creating an animation with a transparent background so that only the plot elements are shown. It turns out that this is possible using the Matplotlib animation objects (note: I've only tried this on Mac). The key elements to doing this are to (1) make the Matplotlib figure background invisible, (2) save the video using a png codec (yes, the image format), and (3) to pass keyword arguments through the animation object to the individual Matplotlib savefig calls. I'll show a simple example below of a circle orbiting in a circle with a trail of points that fade out. (Note: running this code requires installing JSanimation.) First, imports:

In [3]:
# Third-party
from matplotlib import animation
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
from JSAnimation.IPython_display import display_animation

We start by defining how many frames (timesteps) to use in the animation, and how many circles to draw in the trail:

In [4]:
n_frames = 128
n_trails = 8

The circle will orbit in a circle:

In [5]:
t = np.linspace(0, 10, n_frames)
x = np.sin(t)
y = np.cos(t)

Finally, the meat of the code containing the calls to Matplotlib:

In [6]:
fig,ax = plt.subplots(1,1,figsize=(8,8))

ax.set_xlim(-1.1, 1.1)
ax.set_ylim(-1.1, 1.1)

# turn off axis spines
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
ax.set_frame_on(False)

# set figure background opacity (alpha) to 0
fig.patch.set_alpha(0.)

fig.tight_layout()

pt, = ax.plot([], [], linestyle='none', marker='o', ms=15, color='r')

trails = []
for i,alpha in enumerate(np.linspace(1.,0,n_trails)):
    l, = ax.plot([], [], linestyle='none', marker='o', ms=6, alpha=alpha, c='w', zorder=-1000)
    trails.append(l)

def init():
    pt.set_data([], [])
    for trail in trails:
        trail.set_data([], [])
    return (pt,) + tuple(trails)

def update(i):
    ix = i - n_trails

    pt.set_data(x[i], y[i])
    for j,trail in zip(range(len(trails))[::-1],trails):
        if ix+j < 0:
            continue
        trail.set_data(x[ix+j], y[ix+j])
    return (pt,) + tuple(trails)

ani = animation.FuncAnimation(fig, update, n_frames, init_func=init,
                              interval=20, blit=True)

display_animation(ani)
Out[6]:


Once Loop Reflect

Notice the lines that hide the plot elements and make the figure background transparent:

ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
ax.set_frame_on(False)

and

fig.patch.set_alpha(0.)

To save the video out with a transparent background, the other critical arguments are to the save() call, especially the keyword arguments passed through via savefig_kwargs:

In [7]:
ani.save('circle_anim.mov', codec="png",
         dpi=100, bitrate=-1, 
         savefig_kwargs={'transparent': True, 'facecolor': 'none'})