This is document gives a few insights on how to draw axis with d3.js. Different scale types are described first, followed by customization possibilities. It is composed by several interactive examples, allowing to play with the code to understand better how it works.
scaleLinear()
Let's start with the most common type of axis: the linear axis. Basically, the idea is to map a numeric variable to the axis. It is used in most of chart types, like scatterplot or histogram.
Here is the code allowing to add a linear axis in a div
that has the id res
(html code not shown here).
// create svg element
var svg = d3.select("#res")
.append("svg")
.attr("width", 1000)
// Create the scale
var x = d3.scaleLinear()
.domain([0, 100]) // This is what is written on the Axis: from 0 to 100
.range([100, 800]); // This is where the axis is placed: from 100px to 800px
// Draw the axis
svg
.append("g")
.attr("transform", "translate(0,50)") // This controls the vertical position of the Axis
.call(d3.axisBottom(x));
scaleLog()
Very similar to linear scales above,but applies a logarithmic transform to the input domain value before the output range value is computed.
Note: log(0)=-∞, thus the domain
must be strictly positive or strictly negative.
// create svg element
var svg = d3.select("#log_demo")
.append("svg")
.attr("width", 1000)
.attr("height", 200)
// Create the scale
var x = d3.scaleLog()
.domain([1,1000]) // This is what is written on the Axis: from 0 to 100
.range([100, 800]) // This is where the axis is placed: from 100 px to 800px
.base(10)
// Draw the axis
svg
.append("g")
.attr("transform", "translate(0,150)") // This controls the vertical position of the Axis
.call(d3.axisBottom(x).tickFormat(d3.format(".2")))
scalePoint()
Here is the Javascript code allowing to add a linear axis in a div that has the id 'res'.
// create svg element
var svg = d3.select("#ordinal_demo")
.append("svg")
.attr("width", 1000)
.attr("height", 200)
// Create the scale
var x = d3.scalePoint()
.domain(["A", "B", "C", "D", "E"]) // This is what is written on the Axis: from 0 to 100
.range([100, 800]); // This is where the axis is placed: from 100 px to 800px
// Draw the axis
svg
.append("g")
.attr("transform", "translate(0,150)") // This controls the vertical position of the Axis
.call(d3.axisBottom(x));
// Add 1 circle for the group B:
svg
.append("circle")
.attr("cx", x("B"))
.attr("cy", 50)
.attr("r", 8)
scaleBand
The scaleBand()
function is ideal to build categorical axis. It is thus useful for common charts like barplot or boxplot.
Here is the Javascript code allowing to add a categoric axis in a div that has the id 'res'.
// create svg element
var svg = d3.select("#band_demo")
.append("svg")
.attr("width", 1000)
.attr("height", 300)
// Create the scale
var x = d3.scaleBand()
.domain(["A", "B", "C", "D", "E"]) // This is what is written on the Axis: from 0 to 100
.range([100, 800]) // This is where the axis is placed: from 100 px to 800px
.padding([0.8]) // Goes between 0 and 1. Default is 0
// Draw the axis
svg
.append("g")
.attr("transform", "translate(0,250)") // This controls the vertical position of the Axis
.call(d3.axisBottom(x));
// Add one bar for group C:
svg
.append("rect")
.attr("x", x("C") )
.attr("y",100)
.attr("height", 150)
.attr("width", x.bandwidth() )
.style("fill", "#69b3a2")
.style("opacity", 0.5)
axisLeft
All the scale described above can be set vertically.
// create svg element
var svg = d3.select("#vertical")
.append("svg")
.attr("width", 1000)
.attr("height", 300)
// Create the scale
var y = d3.scaleLinear()
.domain([0, 100]) // This is what is written on the Axis: from 0 to 100
.range([290, 10]); // Note it is reversed
// Draw the axis
svg
.append("g")
.attr("transform", "translate(50,0)") // This controls the vertical position of the Axis
.call(d3.axisLeft(y));
It is sometimes useful to rotate the labels of an axis, especially when this labels are quite long.
// create svg element
var svg = d3.select("#rotate")
.append("svg")
.attr("width", 1000)
.attr("height", 300)
// Create the scale
var x = d3.scaleBand()
.domain(["Long name", "Another One", "Here", "And this is", "The end", "ouuuu", "not yet"]) // This is what is written on the Axis: from 0 to 100
.range([0, 800]); // Note it is reversed
// Draw the axis
svg
.append("g")
.attr("transform", "translate(100,100)") // This controls the rotate position of the Axis
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,10)rotate(-45)")
.style("text-anchor", "end")
.style("font-size", 20)
.style("fill", "#69a3b2")
Axis titles aren't built-in to D3's axis component, but are essential for a chart. You can add titles yourself simply by adding an svg text
element. As shown in the chart below:
// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 40, left: 60},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// create svg element, respecting margins
var svg = d3.select("#title")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Add X axis
var x = d3.scaleLinear().domain([0, 100]).range([0, width]);
svg
.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add Y axis
var y = d3.scaleLinear().domain([0, 100]).range([ height, 0]);
svg
.append("g")
.call(d3.axisLeft(y));
// Add X axis label:
svg.append("text")
.attr("text-anchor", "end")
.attr("x", width)
.attr("y", height + margin.top + 20)
.text("X axis title");
// Y axis label:
svg.append("text")
.attr("text-anchor", "end")
.attr("transform", "rotate(-90)")
.attr("y", -margin.left+20)
.attr("x", -margin.top)
.text("Y axis title")
Note: The Y axis title uses a 90° rotation to be readable. It causes the whole coordinate system to rotate. Thus x
and y
attributes for positioning are really tricky to set up properly.
Note: Check the way margins are handled in this example. This is a very common way to proceed in d3.js, as described in this post.
This is my cheat sheet for usual customization I perform on my charts:
svg.append("g") .call(d3.axisBottom(x).tickSize(0))
svg.append("g") .call(d3.axisBottom(x).tickValues(["A", "B", "C"]))
var yAxis = d3.svg.axis().scale(y) .orient("left").ticks(5);
svg.append("g") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x).tickSizeOuter(0))
svg.append("g") .call(d3.axisBottom(x)) .select(".domain").remove()
.css
code).yAxis path { stroke: #B8B8B8; }