Animated GIFs From p5.js
After my first few days getting into creative coding / compform, I reached a point where I wanted to share some animations I created. The problem was that I didn’t know how to get an animated gif.
The sketches on p5.js (editor) are all rendered in an HTML canvas element. It’s easy enough to get a static image (just right click and save), but there’s no out-of-the-box way to save an animation.
Searching lead me to CCapture.js, but I wasn’t able to get this to work. One of the open issues suggests that this library no longer works with current versions of the p5.js library/editor.
CCapture.js actually uses gif.js under the hood. This was a lot simpler to use. Here’s what you need to do.
Guide
These steps assume you’re using the default layout given from editor.p5js.org. Specifically, we’re updating index.html
and sketch.js
.
Also, make sure you’re working from a saved sketch. You want your url to be something like https://editor.p5js.org/vple/sketches/gTK85f8He, not https://editor.p5js.org/. This matters since we’re going to be using a relative path later.
Configure Resources
There are two main files we’ll need: gif.js
and gif.worker.js
.
gif.js
The first one we can add via jsDelivr. In index.html
, add this somewhere in your head
:
<script src="https://cdn.jsdelivr.net/gh/jnordberg/gif.js/dist/gif.js"></script>
This defines GIF
, which is what our code will use to build and render its animated gif.
gif.worker.js
gif.js
needs gif.worker.js
, so we’ll have to provide that. This looks like it’s fetched dynamically, so CORS blocks us from using jsDelivr again.
First, download gif.worker.js
.
Then upload this file into the p5 editor. There’s a dropdown in the directory, next to “Sketch Files”, that you can use to upload a file. Or, create an empty file and copy/paste.
Once you’ve done this, you should see gif.worker.js
in your sketch files.
Configure Encoder
Now that the encoder’s available to us, let’s set it up.
Constants
I recommend setting up a few constants to make later steps slightly easier. These aren’t necessary, but are probably helpful if you’re just creating simple/short gifs.
If you don’t already have a variable that defines the frame rate, create one! This should be the same value that you use to configure p5’s frame rate.
const FPS = 30;
function setup() {
frameRate(FPS);
// ...
}
Next, some constants to control the encoder itself:
const
CREATE_GIF = true,
RECORD_FRAMES = FPS * 5;
CREATE_GIF
allows us to toggle whether or not we want to generate a gif. RECORD_FRAMES
is the number of frames that we want to capture in our gif. In this example, we’re going to get a 5 second gif.
Encoder
Next, we define the encoder. I added this snippet somewhere before setup()
:
if (CREATE_GIF) {
var gif = new GIF({
debug: true,
quality: 0,
workerScript: "./gif.worker.js"
});
gif.on('finished', function(blob) {
window.open(URL.createObjectURL(blob));
});
}
You can find a full list of options here.
Make sure the workerScript
path is correct—this is relative to the top level “Sketch Files” directory.
The second part of this snippet (gif.on
) describes what to do once we’re done rendering our gif. In this case, we open it up in a new window.
GIF Creation
We now have our encoder ready! Add this snippet to the bottom of draw()
:
if (CREATE_GIF) {
if (frameCount <= RECORD_FRAMES) {
gif.addFrame(canvas, {
delay: 1000 / FPS,
copy: true
});
}
if (frameCount == RECORD_FRAMES) {
gif.render();
}
}
gif.addFrame
adds a frame to the gif we’re going to create. Conveniently, it takes our canvas
element.
The options affect how the encoder adds the frame to the final gif. Empirically, using copy
seems to be faster.
delay
specifies how many milliseconds the frame should show for. Setting it to 1000 / FPS
will have our final gif animate at the same rate as the animation in p5.js.
You can tweak this to do some neat stuff—you can scale the delay up/down to slow down/speed up your animation. Especially helpful if it takes a while for you to draw each frame—you can use this to speed up the final gif.
Run It!
We’re all set, so now you just need to run your code. If it’s working, you should see a new window pop up with your gif! You can then right click and save it.