Taking care of gifness

Noah Veltman

WNYC Data News

@veltman

github.com/veltman/gifs

WHY GIFS?

THE PROBLEM

Screen capture doesn't scale.

THE MISSION

...is easy to automate.

 

...accepts you for who you are.

Turn JS animations into gifs or videos in a way that:

RENDER LOOPS

  // Set stuff up

  draw(t) {

    // Draw everything

    requestAnimationFrame(draw);

  }

  requestAnimationFrame(draw);

CANVAS MODULE

  var Canvas = require("canvas");

  var myCanvas = new Canvas(600, 600);

  var context = myCanvas.getContext("2d");

  context.fillStyle = "papayawhip";
  context.fillRect(100, 100, 400, 400);

  fs.writeFile("whipit.png", canvas.toBuffer(), etc);

PROS

Easy to automate

Lots of control

CONS

Canvas only

Lots of dependencies

SVG2PNG MODULE

  var svg2png = require("svg2png"),
      d3 = require("d3"),
      jsdom = require("jsdom"),
      ...

PROS

SVG goodness

CONS

PhantomJS weirdness

GIF.JS + WEB WORKERS

  var gif = new GIF();


  for (var i = 0; i < numFrames; i++) {

    drawFrame(i * duration / frames);

    gif.addFrame(myCanvas, {
      delay: duration / frames,
    });

  }

  gif.render();

GIF.JS + WEB WORKERS

PROS

Browser goodness

On-demand gifs

CONS

Hard to automate

No video

BUT...

My code looks more like...

  d3.selectAll(".districts")
    .transition()
    .delay(function(d,i){
      return i * 20;
    })
    .ease("cubic-in-out")
    .attr("d",newPath);
  $(".box").animate({
    width: "400px",
    height: "200px",
    ...
  });

OPENING THE BLACK BOX

1. Create a transition

2. Check each element

3. Save all their updaters

4. Run them later

OPENING THE BLACK BOX

  dots.transition()
    .something()
    .very()
    .complicated();

  var jumpToTime = dots.record(true);

OPENING THE BLACK BOX

PROS

Kind of works

CONS

D3 only

Can't go backwards

Is bad

LIE TO YOUR BROWSER

RENDER LOOPS

  // Set stuff up

  draw(t) {

    // Draw everything

    requestAnimationFrame(draw);

  }

  requestAnimationFrame(draw);

SPOT THE CODE SMELL

  var fakeTime = 0;

  Date.now = function() {
    return fakeTime;
  };

  window.requestAnimationFrame = function(cb) {
    saveFrame();
    fakeTime += 17;
    setTimeout(cb,0);
  };

PROS

Accepts you for who you are

CONS

Breaks everything else

You should probably still just use screen capture

 

But maybe not?

 

Videos!

PARTING THOUGHTS

Thanks!

Noah Veltman

WNYC Data News

@veltman

BrooklynJS

By veltman

BrooklynJS

  • 1,000