creating a gif of a webgl animation

Hi there,

I’d like to create a gif of an animation I made, which is a fork of this Earth’s Changing Seasons (Blue Marble) Remix / Thomas Ballinger / Observable

I noticed I was unable to download a png of any of the frames of this… Does anyone know if I should be able to use gif.js to to record this animation while it plays? I was hoping someone could tell me if it is possible (and hopefully how!) before I start trying.

Thanks!

2 Likes

Strange, I tried to extract the html canvas from gl into a HTML cell, but it’s blanks too.

<img src=${gl.canvas.toDataURL('image/jpeg', 1.0)}>

I added an ID to the canvas and using d3 select got better results but very unreliable.

<img src="${d3.select('#earth').node().toDataURL('image/jpeg', 1.0)}">

Right clicking on the earth image saving works but unless you can add a step button to the animation then that wont help with saving frames.

Reasons and workarounds are explained in this article:

1 Like

Nice one @mootari adding the

  canvas.value = canvas.getContext("webgl", {preserveDrawingBuffer: true});

Allowed observable to download the PNG file.

1 Like

Here is a wrapper around the original notebook that lets you draw individual frames to a 2D canvas:

2 Likes

I’ve added a gif example to the notebook.

observable-1629294968

2 Likes

Amazing! Thank you so much. Though I am curious how you got the gif to record while playing through the months. I tried adding a scrubber to adjust the months but that caused the gif function to rerun every time the month changed.

Or perhaps you stitched the gif together after individually downloading each frame?

All parameters can be adjusted for each draw. The t argument that gets passed to the drawFrame callback goes from 0 to 1 (excluding 1; the number of steps is determined by the animation duration and the number of frames per second).

You can animate various parameters through t, e.g.:

    return draw({
      canvas, 
      size,
      rotation: t,
      // Step through all months, from 0 up to (but excluding) 12
      month: Math.floor(t * 12),
      // Wiggle around the offset .25 by a distance of -/+ .15
      latitude: .25 + .15 * Math.cos((t+.3) * Math.PI * 2),
    });

month ranges from 0 to 11. The ranges for latitude and rotation are arbitrary, but a delta of 1 means a full rotation for each of them.

1 Like

ah right. was trying to figure out how to adjust that. Thanks again

1 Like

Note that I made an edit to my reply: t * 12

Otherwise you’d miss the last step of the month progression. If you want to be on the safe side, you can write (t * 12) % 12. This also allows you to set a different starting month, e.g. (3 + t * 12) % 12.

2 Likes