Skip to content

Saving HTML canvas animation from browser console

Louis edited this page Mar 20, 2015 · 7 revisions

No cross origin scripts, image download post processing guide

...but otherwise only a slightly modified version of this wonderful answer to a StackOverflow question on how to reproduce a HTML canvas locally using javascript.

Below gisted here is the same code, with actual JS in place of cross-site calls to raw.github... links, which Google Chrome is blocking. Anyone else using this should probably verify their contents (see original question) rather than take my word though! :-) For my own reference.

Click here to jump down to code for saving the images

var jsf  = ["/Demos/b64.js", "LZWEncoder.js", "NeuQuant.js", "GIFEncoder.js"];

/*
   Edit: I've removed the cross-origin call to get github files, and entered here.
   You may want to verify their contents!
*/

// JSF JAVASCRIPT BEGINS HERE

// truncated for readability: see https://gist.github.com/lmmx/04a87c473df61d2f3696

// JSF JAVASCRIPT ENDS HERE

// This post was very helpful!
// http://antimatter15.com/wp/2010/07/javascript-to-animated-gif/

var w = setTimeout(function() { // give external JS 1 second of time to load

    console.log('Starting');

    var canvas = document.getElementById("mycanvas");
    var context = canvas.getContext('2d');
    var shots  = [];
    var grabLimit = 100;  // Number of screenshots to take
    var grabRate  = 100; // Miliseconds. 500 = half a second
    var count     = 0;

    function showResults() {
        console.log('Finishing');
        encoder.finish();
        var binary_gif = encoder.stream().getData();
        var data_url = 'data:image/gif;base64,'+encode64(binary_gif);
        document.write('<img src="' +data_url + '"/>\n');
    }

    var encoder = new GIFEncoder();
    encoder.setRepeat(0);  //0  -> loop forever, 1+ -> loop n times then stop
    encoder.setDelay(500); //go to next frame every n milliseconds
    encoder.start();

    var grabber = setInterval(function(){
      console.log('Grabbing '+count);
      count++;

      if (count>grabLimit) {
        clearInterval(grabber);
        showResults();
      }

      var imdata = context.getImageData(0,0,canvas.width,canvas.height);
      encoder.addFrame(context);

    }, grabRate);

}, 1000);

Saving images

  • Use Ctrl + C in Chrome to select the elements (find the first in the sequence, remove all others, same for the end to give a full sequence)

Run a loop over these elements, open them in new tabs with OpenList and save with (my extension!) TabSave 😃

Actually there's no need to open the images in tabs, just go straight to saving by clicking the pencil icon in TabSave

// process the resultant images by pasting into OneList, then let TabSave do the downloading

imgs = document.querySelectorAll('img');
imglinks = [];
for (i=0;i<imgs.length;i++) {
  imglinks.push(imgs[i].src);
}

If you've got ∞ RAM and/or just a few frames, just copy(imglinks.join('\n')), else slice the array into manageable windows (opening too many tabs in a window can make Chrome croak)

imglinks1 = imglinks.slice(0,20);
imglinks2 = imglinks.slice(21,40);
imglinks3 = imglinks.slice(41,60);
imglinks4 = imglinks.slice(61,80);
imglinks5 = imglinks.slice(81,100);
imglinks6 = imglinks.slice(101,imglinks.length);

copy(imglinks1.join('\n'));
// etc.

Paste into OpenList TabSave (OpenList actually Googles the data-uri...) to have all images download (on my computer the default filename for these data-uri images is download).

Rendering animation

GIMP: Ctrl + Alt + O to add on top of an original layer 👍

Example animation generated this way, from this canvas

Clone this wiki locally