Code Experiment: Converting Canvas Animations To Gifs
Tags: javascript, webdev, animation, coding
Published: 2019-07-02 03:26:49

---
title: Code Experiment: Converting Canvas Animations To Gifs
published: true
description: Hacking together canvas animations, webgl, and different gif creation libraries
tags: javascript, webdev, animation, coding
cover_image: https://thepracticaldev.s3.amazonaws.com/i/na48msdkkqzayjkd8vzj.png
---
I thought I'd try a fun experiment where I show how I approach solving a problem. The idea here is you can see how I work and how messy it is. At each step of the way, I'll show the code I was working with, even if it was messy.

These are in the form of Glitch "remixes", basically easily creating a new copy at each step so the old one has what I was doing before. 

You'll notice a lot of code that makes very little sense. A lot of code commented out. And lots of `console.log`. This is basically how I learn something I'm unfamiliar with. By poking around and seeing what happens. 

My process is basically some mixture of:
* Search for things on Google, Glitch, Codepen and Github
* Run them myself to see how they work
* Comment out code to break it to see what matters and what doesn't
* Add some stuff to see if it works
* Lots of logging variables at different stages to see what happens to them
* Trying to combine different examples

Recently I inherited a project with a fairly simple premise. Or at least I thought so. The idea was to take an animation on HTML canvas and turn it into a cool animated gif. That way you could easily share it on social media. Full disclosure I don't know anything about canvas animation except that it exists.

Turns out there is a lot I don't know. SHOCKING. 

![surprise pikachu](https://thepracticaldev.s3.amazonaws.com/i/e1lfqyg51al07yfdzwne.png)

Also turns out that browsers don't really want you to do that? I should have remember this excellent article [The GIF Is Dead. Long Live the GIF](https://www.popularmechanics.com/technology/a21457/the-gif-is-dead-long-live-the-gif/).

The point of it is that web standards sticklers have been trying to bury the gif for ages. So they aren't exactly eager to build in gif making abilities to web browsers. Meanwhile everyone and their mom thinks animated stuff on the web = gifs. 

But there are some cool things built in to web browsers that I suppose are meant to tempt me to abandon gifs. One is the [MediaRecorder Web API](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder).

A lot of people seem to use it for webcam recording, but I couldn't find many examples that utilized canvas animations. I found one on GitHub called [WebRTC samples Record stream from a canvas](https://webrtc.github.io/samples/src/content/capture/canvas-record/). 

It's using a 3d example but I wanted to use some 2d animation so I ported it to Glitch and tried it out. 

{% glitch proud-sociology app %} 

Next I stumbled upon this simpler [CanvasRecorder](https://smusamashah.github.io/blog/2018/10/26/CanvasRecorder) implementation on Github. I loved it because it really was just one simple readable implementation of the concept.

{% github SMUsamaShah/CanvasRecorder %} 

Ah now that's a great example! As simple as possible so you can understand it easily and play around with it. 

And it worked great. Perfect. I'm done! 

{% glitch resolute-hamburger app %} 

Oh just kidding. It makes a webm not a gif. The web standards people really love the webm but I'm not sure anyone has gotten the memo. You can't share them on Twitter. Oh and it doesn't work in Safari at all. Sigh.

I detoured a bit here exploring Giphy's API, should be capable of converting webm to a gif since the site is. It also has nice social sharing features. But that doesn't solve the Safari or mobile issue. I also learned the hard way that the upload api won't take webm. If I ever need to record an A-frame WebVR scene I've got a start here.

{% glitch subsequent-legal app %} 

So on to various other "solutions". [Gif.js](https://jnordberg.github.io/gif.js/) seems OK. But a lot of the examples I want to use are in CoffeeScript and I really just can't read them very easily.

![I don't know her](https://media.giphy.com/media/wFk7roIpDeXC0/giphy.gif)
<figcaption>Me when I see CoffeeScript</figcaption>

As I said, I like it when examples are simple and in just plain ol' Javascript. It's more likely people are using Javascript than CoffeeScript. Also it's usually easier to go from plain Javascript to CoffeeScript than vice versa.
 
Thank goodness I found this [codepen](https://codepen.io/ford/pen/RKYvNy
) that includes it in a simple example. Though hilariously it's for demonstrating a problem with gif.js

{% codepen https://codepen.io/ford/pen/RKYvNy %} 

I get it working on top of my old one that's nice

{% glitch fir-decimal app %} 

At this point the fans on my computer come on and I'm worried it might fly away.

![my laptop getting ready to fly](https://media.giphy.com/media/caVdtPeN83dza/giphy.gif)

It says "Works in browsers supporting: Web Workers, File API and Typed Arrays" hmm. Time to test on mobile, which is easy since it's on Glitch. 

I'm shocked but it works!! Also works in my mortal enemy AKA Safari AKA the new IE.  That's cool. 

On to the next candidate. [ccapture](https://github.com/spite/ccapture.js/). But I read the docs and it uses gif.js sooooo I'm gonna bet it's gonna use more resources and my fans are already getting a workout. I skip it. 

Now I could take a detour into generating a gif server side but I've already spent more time on this than I planned so I will sadly leave that. Plus I have some experience with node "canvas"...and it isn't the same as "real" canvas. 

Next up is [jsgif](https://github.com/antimatter15/jsgif) but I skim the docs and immediately give up. 

Basically the conclusion I've come to is all the solutions are bad and should be banned. 

Looks like gif.js is the "best" solution. 

I'm curious to see what it can do. Like the final app may use just "regular" canvas but I've also thought about using WebGL. I have a bunch of A-frame examples lying around and A-frame is Three.js which is WebGL. 

Sadly it says `TypeError: Argument 1 of CanvasRenderingContext2D.drawImage could not be converted to any of: HTMLImageElement, SVGImageElement, HTMLCanvasElement, HTMLVideoElement, ImageBitmap.`

I hack around a bit but eventually I realize I'm spending too much time on this (that's why I use a timer when I work because I can easily get sucked into tangents). 

Well uh maybe it's A-frame's fault. I know there is a nice [Three.js example on Glitch](https://glitch.com/~threejs) so I'll see if that will work.

Same error. But I remember CCapture had some cool 3D gifs so maybe it needs something in there. Now here I have to note that on projects like this that aren't high priority I'm not going to dive into things deeply and figure out how they work. If you're building something you want to last for years, you might want to figure out how this stuff works on a deeper level. I'm not. 

{% glitch half-thyme app %} 

At this point I'm not even bothering with a UI. If you wanna try it out. You can use start() and stop () in the browser console. It works!

Now I do something v bad and try A-Frame even though why??? The initial [example I tried](https://glitch.com/~starter-aframe-fancy) was rather complex and my computer now feels like it might be on fire?

![computer is on fire](https://media.giphy.com/media/l4pTjY0qhA2c5abII/giphy.gif) 

I had to force quit the browser and then I tried it with a simple example and it worked! 

{% glitch silly-poison app %} 

Nice but this isn't what I'm supposed to be doing. Oops. 

So I think the gif.js "solution" is the best one. I cleaned up the app so I can work on it later (or my colleague can) or you can "remix" it and do something cool. 

{% glitch canvas-to-gif app %} 
<figcaption>Canvas example from this [Codepen](https://codepen.io/agar3s/pen/pJpoya)</figcaption>

I hope to do another post where I work on the final product which I promise is cooler. 

Since this is my first time doing this kind of thing, I'd love to know your tips and tricks!