How to create a D3.js area chart

Introduces how to create a basic area chart in D3.

Example program

View code

Example code

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>D3 Area Chart</title>
  <script src="https://d3js.org/d3.v7.min.js"></script>
</head>

<body>
  <script>
    // 1. Prepare data
    var dataset = [
      [1, 15],
      [5, 25],
      [25, 30],
      [85, 40],
      [100, 42],
      [220, 40],
      [250, 50],
      [330, 95],
      [410, 30],
      [475, 44],
      [480, 50]
    ];

    var width = 400; // Graph width
    var height = 300; // Graph height
    var margin = { "top": 30, "bottom": 60, "right": 30, "left": 60 };

    // 2. Set SVG area
    var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);

    // 3. Set axis scales
    var xScale = d3.scaleLinear()
      .domain([0, d3.max(dataset, function (d) { return d[0]; })])
      .range([margin.left, width - margin.right]);

    var yScale = d3.scaleLinear()
      .domain([0, d3.max(dataset, function (d) { return d[1]; })])
      .range([height - margin.bottom, margin.top]);

    // 4. Display axes
    var axisx = d3.axisBottom(xScale).ticks(5);
    var axisy = d3.axisLeft(yScale).ticks(5);

    svg.append("g")
      .attr("transform", "translate(" + 0 + "," + (height - margin.bottom) + ")")
      .call(axisx)
      .append("text")
      .attr("fill", "black")
      .attr("x", (width - margin.left - margin.right) / 2 + margin.left)
      .attr("y", 35)
      .attr("text-anchor", "middle")
      .attr("font-size", "10pt")
      .attr("font-weight", "bold")
      .text("X Label");

    svg.append("g")
      .attr("transform", "translate(" + margin.left + "," + 0 + ")")
      .call(axisy)
      .append("text")
      .attr("fill", "black")
      .attr("text-anchor", "middle")
      .attr("x", -(height - margin.top - margin.bottom) / 2 - margin.top)
      .attr("y", -35)
      .attr("transform", "rotate(-90)")
      .attr("font-weight", "bold")
      .attr("font-size", "10pt")
      .text("Y Label");

    // 5. Display area
    svg.append("path")
      .datum(dataset)
      .attr("fill", "rgba(70, 130, 180, 0.3)")
      .attr("d", d3.area()
        .x(function (d) { return xScale(d[0]); })
        .y1(function (d) { return yScale(d[1]); })
        .y0(yScale(0))
      );

    svg.append("path")
      .datum(dataset)
      .attr("fill", "none")
      .attr("stroke", "steelblue")
      .attr("stroke-width", 1.5)
      .attr("d", d3.line()
        .x(function (d) { return xScale(d[0]); })
        .y(function (d) { return yScale(d[1]); })
      );
  </script>
</body>

</html>

Example code explanation

The scatter plot tutorial explains how to create graphs based on scatter plots, and the line graph tutorial explains how to create line graphs. An area chart can be created with small changes from a line chart.

1. Prepare data

Prepare an object to set margins.

var margin = { "top": 30, "bottom": 60, "right": 30, "left": 60 };

The bottom and left margins are set larger to display the axes.

2. Set SVG area

Set the SVG display area.

3. Set axis scales

Set the axis scales.

d3.scaleLinear()

The code above sets a function that converts the range set with domain to the range set with range. It creates functions that convert line graph coordinates into screen pixel values.

4. Display axes

Use D3’s d3.axisBottom() and d3.axisLeft() functions to set axis elements. Pass the axis-scale functions as arguments and call them with call, and SVG elements are added automatically.

var axisx = d3.axisBottom(xScale).ticks(5);
var axisy = d3.axisLeft(yScale).ticks(5);

svg.append("g")
  .attr("transform", "translate(" + 0 + "," + (height - margin.bottom) + ")")
  .call(axisx)

svg.append("g")
  .attr("transform", "translate(" + margin.left + "," + 0 + ")")
  .call(axisy)

.ticks() controls the number of axis ticks. Set it with an integer.

After calling the axes, add axis labels with text elements.

  .append("text")
  .attr("fill", "black")
  .attr("x", (width - margin.left - margin.right) / 2 + margin.left)
  .attr("y", 35)
  .attr("text-anchor", "middle")
  .attr("font-size", "10pt")
  .attr("font-weight", "bold")
  .text("X Label");

  .append("text")
  .attr("fill", "black")
  .attr("x", -(height - margin.top - margin.bottom) / 2 - margin.top)
  .attr("y", -35)
  .attr("transform", "rotate(-90)")
  .attr("text-anchor", "middle")
  .attr("font-weight", "bold")
  .attr("font-size", "10pt")
  .text("Y Label");

"text-anchor" is an attribute for aligning text positions. Here it is set to "middle" for center alignment. Each label is moved by 35px so it does not overlap the axis.

5. Display the area

Display the area chart with a "path" element. This is the part that differs from a line chart.

svg.append("path")
  .datum(dataset)
  .attr("fill", "rgba(70, 130, 180, 0.3)")
  .attr("d", d3.area()
    .x(function(d) { return xScale(d[0]); })
    .y1(function(d) { return yScale(d[1]); })
    .y0(yScale(0))
  );

svg.append("path")
  .datum(dataset)
  .attr("fill", "none")
  .attr("stroke", "steelblue")
  .attr("stroke-width", 1.5)
  .attr("d", d3.line()
    .x(function(d) { return xScale(d[0]); })
    .y(function(d) { return yScale(d[1]); })
  );

Data binding uses datum as follows.

.datum(dataset)

Unlike data, which binds individual data items, it adds the entire data set to "path". Also, "rgba(70, 130, 180, 0.3)" is used when specifying the color. Set R, G, and B values from 0 to 255, and set the alpha value, or transparency, from 0 to 1. Transparency can also be set with the "opacity" attribute, but use rgba when you want to change the transparency of the "fill" and "stroke" attributes separately. Since "stroke" is not set here, either method is fine.

When drawing the area, set the "d" attribute of path with the following D3 method.

d3.area()
  .x(function(d) { return xScale(d[0]); })
  .y1(function(d) { return yScale(d[1]); })
  .y0(yScale(0))

Set the function that specifies the x coordinate in .x(), the lower y coordinate, here y=0, in y0, and the upper y coordinate in y1.

The second "path" sets the boundary line, just like a line chart. Remove it if it is not needed.

d3.line()
  .x(function(d) { return xScale(d[0]); })
  .y(function(d) { return yScale(d[1]); })

The code above is the function that creates the "d" attribute of the boundary "path".

Closing

Bar charts and scatter plots can also be created with the same algorithm. Refer to those pages as well.