Did you know that you can navigate the posts by swiping left and right?

D3 Area Chart

June 28, 2017, July 21, 2017 | Comments

category: VISUALIZATION
d3 html css javascript

Quite similar to line chart, area chart could also be used to demonstrate the trends over time for comparison. In this post, I’d like to use the same data in last blog from W3School Browser Statistics, but to draw an area chart to show the market share change by different browsers.

As you would see, area chart by D3 uses d3.area() function, also under d3-shape module.

var area = d3.area()
    .x(function(d,i) { return xRange(d.data.Date);  })
    .y0(function(d) { return yRange(d[0]);  })
    .y1(function(d) { return yRange(d[1]);  });  

Essentially, I use d3.area() to generate an area which is defined by two bounding lines. In this specific example, the two lines share the same x-value which is time series value. However, the y-values differ by y0 and y1. It uses curveLinear curve to produce a clockwise polygon and (x1, y1) renders the topline first then (x0, y0) render the bottomline later.

This area function is called later to generate the paths.

browser.append("path")
      .attr("class", "area")
      .style("fill", function(d) { return color(d.key); })
      .attr("d", area);

Here is the full code:

<style>
svg {
    width: 100%;
    height: 100%;
    position: center;
}

#browser {
   background-color: lightgrey;
}

.browser:hover{
    fill: darkgreen;
}

</style>

<svg id="browser" width="950" height="500"></svg>

<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var margin = {top: 30, right: 30, bottom: 30, left: 30};
var width = document.getElementById("browser").getBoundingClientRect().width-100;
var height = 400;

var parseTime = d3.timeParse("%b-%y");

var color = d3.scaleOrdinal(d3.schemeCategory10);

var g = d3.select("#browser")
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var xRange = d3.scaleTime()
        .rangeRound([0, width]);

var yRange = d3.scaleLinear()
    .range([height, 0]);

var stack = d3.stack();

var area = d3.area()
    .x(function(d,i) { return xRange(d.data.Date);  })
    .y0(function(d) { return yRange(d[0]);  })
    .y1(function(d) { return yRange(d[1]);  });

d3.csv("/blog/data/browser_statistics.csv",function(d, i, columns) {
    d.Date = parseTime(d.Date);
    for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
    return d;
    },
    function(error,data){
    if (error) throw error;
    
var browsers = data.columns.slice(1);

xRange.domain(d3.extent(data, function(d) { return d.Date; }));
yRange.domain([0,100]);
color.domain(browsers);

stack.keys(browsers);

var browser = g.selectAll(".browser")
    .data(stack(data))
    .enter()
    .append("g")
    .attr("class", "browser");

  browser.append("path")
      .attr("class", "area")
      .style("fill", function(d) { return color(d.key); })
      .attr("d", area);

  browser.append('text')
      .datum(function(d) { return d; })
      .attr('transform', function(d) { return 'translate(' + xRange(data[0].Date) + ',' + yRange(d[0][0]) + ')'; })
      .attr('x', 3) 
      .attr('dy', '.35em')
      .style("font", "10px sans-serif")
      .text(function(d) { return d.key; });

  g.append("g")
      .attr("class", "axis")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(xRange))
      .style("text-anchor", "middle")
      .attr("dx", "-.1em");

  g.append("g")
      .attr("class", "axis")
      .call(d3.axisLeft(yRange))
      .append("text")
      .attr("x",3)
      .attr("y", 6)
      .attr("dy", "0.71em")
      .attr("fill", "#000")
      .attr("text-anchor", "start")
      .text("Market Share, %")
      .attr('fill-opacity', 1);
});

</script>  

Reference:

(1). D3 API Reference, https://github.com/d3/d3/blob/master/API.md.
(2). Multi-Series Line Chart, https://bl.ocks.org/mbostock/3884955.