D3 is an interactive JavaScript library for data visualization. It uses Scalar Vector Graphics (SVG) coupled with HTML and CSS to display charts and figures that illustrate the numeric data. You can also use D3 to make line charts. Here is a step-by-step guide on how to make a line chart using D3.
Before even starting to code, we need a data set to base our chart on. For this example, we will take a basic 2D array of random numbers. Our array is:
var dataset1 = [
[1,1], [12,20], [24,36],
[32, 50], [40, 70], [50, 100],
[55, 106], [65, 123], [73, 130],
[78, 134], [83, 136], [89, 138],
[100, 140]
];
The first thing we need to do is import the D3 script using the src
attribute and then initialize our SVG container with the appropriate width and height:
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="400"></svg>
To make the chart look more centered and clear, we need to set a margin for our SVG. We are making four variables; svg
, margin
, width
, and height
. svg
is initialized with the 500px width and 400px height. These widths and heights are then adjusted according to the 200px margin.
var svg = d3.select("svg"),
margin = 200,
width = svg.attr("width") - margin,
height = svg.attr("height") - margin
For discrete data visualization on the x-axis, we construct a Linear Scale or scaleLinear()
. scaleLinear()
uses the linear equation (y = mx + c) to interpolate domain and range across the axis:
var xScale = d3.scaleLinear().domain([0, 100]).range([0, width]),
yScale = d3.scaleLinear().domain([0, 200]).range([height, 0]);
We need to add a title, x-axis label, and y-axis label to our plot. For this purpose, we first append text
to our svg
, then we set the position, style, and actual text attribute. To rotate our text for the y-axis, we use transform
and specify the angle of rotation.
// Step 5
// Title
svg.append('text')
.attr('x', width/2 + 100)
.attr('y', 100)
.attr('text-anchor', 'middle')
.style('font-family', 'Helvetica')
.style('font-size', 20)
.text('Line Chart');
// X label
svg.append('text')
.attr('x', width/2 + 100)
.attr('y', height - 15 + 150)
.attr('text-anchor', 'middle')
.style('font-family', 'Helvetica')
.style('font-size', 12)
.text('Independant');
// Y label
svg.append('text')
.attr('text-anchor', 'middle')
.attr('transform', 'translate(60,' + height + ')rotate(-90)')
.style('font-family', 'Helvetica')
.style('font-size', 12)
.text('Dependant');
Now, we need to add both of the axes. For the x-axis, we call d3.axisBottom
because we need to align it at the bottom of the canvas. For the y-axis, we call d3.axisLeft
because we want to align it to the left of the canvas.
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
svg.append("g")
.call(d3.axisLeft(yScale));
We now need to add a dot for every coordinate in our dataset1
. We supply dataset1
to the data
attribute and then make a circle for each coordinate. The cx
specifies the horizontal position of the circle, while cy
specifies the vertical position of the circle. Moreover, r
specifies the radius of the circle. Then, we translate all the data points to match the translation of our axes. Lastly, we color the data points red by giving the #CC0000
hex-code:
svg.append('g')
.selectAll("dot")
.data(dataset1)
.enter()
.append("circle")
.attr("cx", function (d) { return xScale(d[0]); } )
.attr("cy", function (d) { return yScale(d[1]); } )
.attr("r", 2)
.attr("transform", "translate(" + 100 + "," + 100 + ")")
.style("fill", "#CC0000");
Finally, we need to connect all the dots we added in step 8. To make a line, we will use the line generator of d3 by invoking d3.line()
. This line generator can then be used to compute the d
attribute of an SVG path
element. We append path
to our SVG and then specify the class as line
. Then we transform it like we transformed our axes and datapoints earlier, and lastly, we style the line accordingly.
var line = d3.line()
.x(function(d) { return xScale(d[0]); })
.y(function(d) { return yScale(d[1]); })
.curve(d3.curveMonotoneX)
svg.append("path")
.datum(dataset1)
.attr("class", "line")
.attr("transform", "translate(" + 100 + "," + 100 + ")")
.attr("d", line)
.style("fill", "none")
.style("stroke", "#CC0000")
.style("stroke-width", "2");