block by veltman f102967738c9c90906d77c7fff20399a

Canvas animation to video

Full Screen

Converting a canvas animation to a video with the MediaRecorder API.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<canvas width="960" height="500"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script>
var canvas = document.querySelector("canvas"),
    context = canvas.getContext("2d"),
    width = +canvas.width,
    height = +canvas.height;

var projection = d3.geoOrthographic().scale(195).translate([width / 2, height / 2]).precision(0.1);

var path = d3.geoPath().projection(projection).context(context);

d3.json("/mbostock/raw/4090846/world-110m.json", function(err, world) {
  var land = topojson.feature(world, world.objects.land),
      mesh = topojson.mesh(world, world.objects.countries, function(a, b) {
        return a !== b;
      });

  var data = [],
    stream = canvas.captureStream(),
    recorder = new MediaRecorder(stream, { mimeType: "video/webm" });

  var timer = d3.timer(function(t) {
    t = t / 3000;
    if (t < 1) {
      draw(t);
    } else {
      recorder.stop();
      timer.stop();
    }
  });

  recorder.ondataavailable = function(event) {
    if (event.data && event.data.size) {
      data.push(event.data);
    }
  };

  recorder.onstop = () => {
    var url = URL.createObjectURL(new Blob(data, { type: "video/webm" }));
    d3.select("canvas").remove();
    d3.select("body")
      .append("video")
      .attr("src", url)
      .attr("controls", true)
      .attr("autoplay", true);
  };

  recorder.start();

  function draw(t) {
    projection.rotate([360 * t]);

    context.lineWidth = 1;

    context.fillStyle = "#fff";
    context.fillRect(0, 0, width, height);

    context.strokeStyle = "#222";
    context.beginPath();
    path({ type: "Sphere" });
    context.stroke();

    context.fillStyle = "#222";
    context.beginPath();
    path(land);
    context.fill();

    context.strokeStyle = "#fff";
    context.beginPath();
    path(mesh);
    context.stroke();
  }
});
</script>