This stacked area chart is constructed from a TSV file storing the market share of several popular web browsers over the last year. Data is from Clicky Web Analytics. The chart employs conventional margins and a number of D3 features:
xxxxxxxxxx
<meta charset="utf-8">
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
// Commented version of
// https://bl.ocks.org/mbostock/3885211
// Variables
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 50},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom;
// Date Parser takes in Date string and returns JS Data Object
var parseDate = d3.timeParse("%Y %b %d");
// Define x, y, and z (color) scales
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(d3.schemeCategory10);
// Define D3 Stack generator function
var stack = d3.stack();
// Define D3 Area generator function
// "d" will come from the stack generator function
var area = d3.area()
.x(function(d, i) { return x(d.data.date); })
.y0(function(d) { return y(d[0]); })
.y1(function(d) { return y(d[1]); });
// SVG G to provide D3 Margin Convention
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Define variable to give us access to AJAX callback function data
var outsideData;
// CSV AJAX call to ingest data
// data file requested: data.csv
// function to process data: type
// - note function hoisting - type function is at the bottom
// function to be used on call back: function(error, data) {...}
d3.tsv("data.tsv", type, function(error, data) {
if (error) throw error;
// assign internal data variable to outsideData variable so we can see data
// once the AJAX callback function has been run.
outsideData = data;
// Get the keys by taking a slice off of the column headings
var keys = data.columns.slice(1);
// X axis domain is all the dates represented in the data
x.domain(d3.extent(data, function(d) { return d.date; }));
// Z color scale needs colors defined so use the keys
z.domain(keys);
// Use the keys array to define the keys operator of the stack generator function
stack.keys(keys);
// Data join
// Binds value returned from passing the data into stack generator function
// We are generating layers
// So each browser gets it's own layer.
var layer = g.selectAll(".layer")
.data(stack(data))
.enter().append("g")
.attr("class", "layer");
// For each "g.layer" element above, append a path
// Then use the area function to create the area shape based on the bound data
layer.append("path")
.attr("class", "area")
.style("fill", function(d) { return z(d.key); })
.attr("d", area);
// Given data filter out any laayrs that are large enough to warrant labeling
// Then append text such that it inherits the __data__ property
// Then use that data property to place the text as well as create text designating the browser
layer.filter(function(d) { return d[d.length - 1][1] - d[d.length - 1][0] > 0.01; })
.append("text")
.attr("x", width - 6)
.attr("y", function(d) { return y((d[d.length - 1][0] + d[d.length - 1][1]) / 2); })
.attr("dy", ".35em")
.style("font", "10px sans-serif")
.style("text-anchor", "end")
.text(function(d) { return d.key; });
// Create the X Axis
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Create the Y Axis
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(10, "%"));
});
// Function to process the data when it gets ingested by the AJAX call
function type(d, i, columns) {
d.date = parseDate(d.date);
for (var i = 1, n = columns.length; i < n; ++i) d[columns[i]] = d[columns[i]] / 100;
return d;
}
</script>
https://d3js.org/d3.v4.min.js