Skip to content

Instantly share code, notes, and snippets.

@Fil
Forked from veltman/draw.js
Last active June 13, 2019 21:20
Show Gist options
  • Save Fil/f791ca9c519f718c72fc02dc1850ff0d to your computer and use it in GitHub Desktop.
Save Fil/f791ca9c519f718c72fc02dc1850ff0d to your computer and use it in GitHub Desktop.
D3 frames to video

This amazing script by Noah Veltman allows to create videos from d3.

install

npm install canvas topojson d3 rw

run

node draw.js | ffmpeg -y -c:v png -f image2pipe -r 20 -i - -an -c:v libx264 -pix_fmt yuv420p -movflags +faststart myvideo.mp4

enjoy

// Pipe to ffmpeg with something like:
// node draw.js | ffmpeg -y -c:v png -f image2pipe -r 20 -i - -an -c:v libx264 -pix_fmt yuv420p -movflags +faststart myvideo.mp4
var Canvas = require("canvas"),
d3 = require("d3"),
topojson = require("topojson"),
rw = require("rw"),
world = require("./world-110m.json");
var width = 960,
height = 540;
var canvas = new Canvas(width, height),
context = canvas.getContext("2d");
var countries = topojson.feature(world, world.objects.countries),
mesh = topojson.mesh(world, world.objects.countries);
var projection = d3.geoOrthographic()
.scale(240)
.translate([width / 2, height / 2])
.clipAngle(90)
.precision(.1);
var path = d3.geoPath()
.projection(projection)
.context(context);
// Draw 60 frames
d3.range(600).forEach(function(frame){
// Spin the globe a bit more each time
projection.rotate([frame * 0.6]);
context.clearRect(width, height);
// Water
context.fillStyle = "#23b4d8";
context.beginPath();
path({type: "Sphere"});
context.fill();
// Countries
countries.features.forEach(function(country, i){
context.fillStyle = d3.interpolateRainbow(Math.sin(i + frame/10));
context.beginPath();
path(country);
context.fill();
});
// Borders
context.beginPath();
path(mesh);
context.stroke();
// Pipe to stdout but squash EPIPE
rw.writeFileSync("/dev/stdout", canvas.toBuffer());
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment