d3.js from the shell
d3.js is a great library for producing visualizations on the web. What if you want the power and syntax of d3, but don’t have or want a browser? The combination of node and the npm library jsdom can get you there.
What you’ll need
- A shell
node
,npm
should come along
Minimal working example
This is going to assume that you only want d3 and jsdom installed
locally. We will need two libraries from npm
, d3
and jsdom
. First
cd
into the directory you want create the visualization in. We can get
the libraries by running
npm install d3
npm install jsdom
Make a new file called myfigure.js
and start to edit it.
First, we need to get variables referencing the libraries. In node, we
do that with require
s.
const d3 = require("d3")
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
d3
was built for the web and expects a top-level document
variable.
This is what jsdom
is for. It emulates a DOM using only JavaScript. We
need to make that top level document variable using jsdom
.
const { document } = (new JSDOM()).window;
In case you aren’t aware of that ‘variable in curly brace’ syntax, that is called destructuring and is a useful language feature.
We can now make use of d3 to draw something! I’m going to keep things simple and just draw some red circles.
We use d3’s select
function on our ‘fake’ document
, and then we are
off and running. Let’s make a svg
element.
var width = 1000;
var height = 1000;
var svg = d3.select(document).select("body").append("svg")
.attr('xmlns', 'http://www.w3.org/2000/svg')
.attr("width", width)
.attr("height", height);
Bind some data…
var data = [1, 250, 750]
svg.append("g").selectAll("circle")
.data(data)
.enter("circle")
.append("circle").attr("cx", d => d)
.attr("cy", "250")
.style("fill", "red")
.attr("r", "25")
And then print to standard output.
console.log(svg.node().outerHTML)
Here’s the entire file:
// myfigure.js
const d3 = require("d3")
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const { document } = (new JSDOM()).window;
var width = 1000;
var height = 1000;
var svg = d3.select(document).select("body").append("svg")
.attr('xmlns', 'http://www.w3.org/2000/svg')
.attr("width", width)
.attr("height", height);
var data = [1, 250, 750]
svg.append("g").selectAll("circle")
.data(data)
.enter("circle")
.append("circle").attr("cx", d => d)
.attr("cy", "250")
.style("fill", "red")
.attr("r", "25")
console.log(svg.node().outerHTML)
Now in your shell you should be able to run the script with node.
node myfigure.js
If it goes well, you should see the svg XML printed.
Now you could pipe this into other programs or just redirect this to a file.
node myfigure.js > myfigure.svg
Open the svg file up in your favorite vector image program and check it out!