Interactive Data Visualization for the Web, written by Scott Murphy is a great introduction to using D3.js and begin to visualize your data. However, it was written for version 3, and version 4 came out earlier this year. I started working through the examples in CodePen and added d3 with their quick and easy framework dropdown. This adds the newest version which I hadn’t realized was so different than the one used in the book. I decided to stick with it and work out the examples using the new version. This post will help you translate the examples into d3.js version 4.
Bar Charts using d3.js version 4
In this bar chart example you first setup the xScale with an scale ordinal. Here’s the version 3 code, followed by the version 4.
/* VERSION 3 */ var xScale = d3.scale.ordinal() .domain(d3.range(dataset.length)) .rangeRoundBands([0, w], 0.05); /* VERSION 4 */ var xScale = d3.scaleBand() .domain(d3.range(dataset.length)) .rangeRound([0, w]) .paddingInner(0.05);
One of the most consistant changes is dropping the first scale method and combining it with the call to the specific method. For example d3.scale.linear is now d3.scaleLinear. In the above example the scale is still an ordinal scale in version 4, it’s now a specific ordinal scale for bands. You also have d3.scalePoint and the standard d3.scaleOrdinal at your disposal.
Similarly we don’t need to specify the .rangeRoundBands, because we’re already talking about bands. This changes to just .rangeRound. However you can no longer define a padding in the rangeRound, so there is another method for doing just that, .paddingInner.
Another change for our bar chart is determining the width of each individual bar. Our scaleBand scale has a method called band.bandwidth() that returns with width of each band so that they evenly take up the allotted space. In version 3 you used rangeBands() which took a log and a high value, often [ 0 , width ], and also a second parameter that added spacing between the bands.
/* VERSION 3 */ .attr("width", xScale.rangeBand()) /* VERSION 4 */ .attr("width", xScale.bandwidth())
The new version makes it much easier because it knows on a scaleBand you’re going to want to know how wide to make each band so they evenly distribute on the range that we declare with band.rangeRound() (or just band.range() ).
Time for Pie Charts
With version 4 you can use svg or canvas to draw your shapes. Because of this only a couple of changes are needed to follow the Pie Chart tutorial.
Here’s how the two versions compare:
/* VERSION 3 */ var pie = d3.layout.pie(); var w = 300; var h = 300; var outerRadius = w / 2; var innerRadius = 0; var arc = d3.svg.arc() .innerRadius(innerRadius) .outerRadius(outerRadius); var arcs = svg.selectAll("g.arc") .data(pie(dataset)) .enter() .append("g") .attr("class", "arc") .attr("transform", "translate(" + outerRadius + ", " + outerRadius + ")"); /* VERSION 4 */ var pie = d3.pie(); var w = 300, h = 300; var outerRadius = w / 2; var innerRadius = w / 3; var arc = d3.arc() .innerRadius(innerRadius) .outerRadius(outerRadius); var arcs = svg.selectAll('g.arc') .data(pie(dataset)) .enter() .append('g') .attr('class', 'arc') .attr('transform', 'translate(' + outerRadius + ', ' + outerRadius + ')');
You’ll see the only difference is the initialization change from d3.layout.pie() to d3.pie() and the call for the arc generator from d3.svg.arc() to d3.arc().
This example also uses a set of colors that D3.js comes with that we can use to speed up development and not set specific colors. Here’s the comparison between versions:
/* VERSION 3 */ var color = d3.scale.category10(); /* VERSION 4 */ var color = d3.scaleOrdinal(d3.schemeCategory10);
Again a small difference but you’re code wont work if you don’t use the new syntax. Also in version 4 you get three versions of a 20 color scheme category you can access with
Also in version 4 we get a new module called d3-scale-chromatic. This offers a more powerful color scheme. You will have to make sure to include the module when you need to use it. Read more and check out all of the schemes on the modules github.
Use the force
Using data visulizations in d3.js version 4 is a little different and splits everything out into batches of methods for each part of the visualization. You create a new force similar to other shapes and layouts by using the updated d3.forceSimulation. This is your simulation and there a several methods for
/* VERSION 3 */ var simulation = d3.layout.force() .nodes(dataset.nodes) .links(dataset.edges) .size([w, h]) .linkDistance() .charge([-100]) .start(); /* VERSION 4 */ var simulation = d3.forceSimulation(dataset.nodes) .force('charge', d3.forceManyBody()) .force('link', d3.forceLink(dataset.links)) .force('center', d3.forceCenter(width / 2, height / 2)); simulation.nodes(dataset.nodes) .on('tick', ticked); simulation.force('link') .links(dataset.links);
We start the same by dropping the extra layout method and just use d3.forceSimulation(), but the next step is accessing the .force methods of the simulation. Each of these return the force of the specified name to create a new simulation to layout.
Mapping with GeoJSON
The examples for GeoJSON in d3.js version 4 are very similar to version 3, with just a couple changes that we’ve seen in all of the past examples.
/* VERSION 3 */ var projection = d3.geo.albersUsa() .translate([w/2, h/2]); var path = d3.geo.path() .projection(projection); /* VERSION 4 /* var projection = d3.geoAlbersUsa() .translate([width/2, height/2]); var path = d3.geoPath() .projection(projection);
With these updates you should be able to make it through all of the examples in Interactive Data Visualization for the Web and get you started on your journey with d3.js version 4 data visualizations.