Creating great looking animations in Julia is shockingly easy thanks for the Plots package and some macro magic. Here we will learn how to turn data into high quality animations. We will learn about the @animate
macro, frames and the gif
function.
Two Steps to Animations
To create animations we simply generate frames with the @animate
macro and then generate a file with the gif
function. Both are part of the Plots package from Julia, so we have to start with using Plots
to make that package available. Next create the data we will plot, which is a simple sine wave. Then we generate the frame with the @animate
macro and animate them with the gif
function. This is the code and the resulting animation.
using Plots
x = collect(1:0.1:30)
y = sin.(x)
df = 2
anim = @animate for i = 1:df:length(x)
plot(x[1:i], y[1:i], legend=false)
end
gif(anim, "tutorial_anim_fps30.gif", fps = 30)

Macros and Meta-Programming
The @animate
macro deserves some extra attention, because it looks like magic. Macros are related to a concept called meta-programming. In Julia, all code is a data structure that can be manipulated in a similar way to all other data structures. This effectively means that we can write code that manipulates our code. That’s what a macro is, a function that modifies code. In our case, the code being modified is the for loop behind our @animate
macro. It is modified in a way that it catches the frame at the end of each loop iteration and saves it into anim
. We can create code that does the same job ourselves.
anim = Plots.Animation()
for i = 1:df:length(x)
plot(x[1:i], y[1:i], legend=false)
Plots.frame(anim)
end
gif(anim, "tutorial_anim_fps30.gif", fps = 30)
We use the Plots.Animation()
function to create our animation object where we will store our frames. During the for loop we then call Plots.frame(anim)
to store the frame after each iteration in our anim
object. These are the essential steps that the @animate
macro takes care of. If you want to learn what the macro does in detail you can call @macroexpand
on it.
@macroexpand @animate for i = 1:df:length(x)
plot(x[1:i], y[1:i], legend=false)
end
There is another macro that is even more convenient. The @gif
macro. It saves us from having to call gif()
on our anim
object.
@gif for i = 1:df:length(x)
plot(x[1:i], y[1:i], legend=false)
end
This directly displays the animation if interactive Julia is available for it. The downside of this is that we do not save the animation to disk and we do not have an anim
object available to do more animations later. It is most useful to quickly troubleshoot animations interactively.
Beyond plot()
The @animate macro supports animations of anything that can be plotted with Plots. For example, we can animate a heatmap.
anim = @animate for i = 1:100
mat = rand(0:100, 32, 32)
heatmap(mat, clim=(0,255))
end
gif(anim, "tutorial_heatmap_anim.gif", fps = 10)

The frame that is being caught is the state of the active figure at the end of the for loop. The for loop itself gives us a great deal of control, how many frames we want to create. For example in the previous examples, I skipped frames with the df
variable.
That’s it for animations. To learn more you can take a look at the official Plots documentation.