Skip to content

Instantly share code, notes, and snippets.

@jwilber
Last active October 14, 2018 04:50
Show Gist options
  • Save jwilber/998faff3082b8c9bf250b51565541dff to your computer and use it in GitHub Desktop.
Save jwilber/998faff3082b8c9bf250b51565541dff to your computer and use it in GitHub Desktop.
stacked area chart
license: mit
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.25.6/d3-legend.min.js"></script>
<style>
g.tick line {
opacity: .4;
stroke: sandybrown;
}
path.domain {
stroke: sandybrown;
opacity: .4;
}
</style>
</head>
<body>
<script src="stackedarea2.js"></script>
</body>
</html>
day titanic avatar akira frozen deliverance avengers
1 20 8 3 0 0 0
2 18 5 1 13 0 0
3 14 3 1 10 0 0
4 7 3 0 5 27 15
5 4 3 0 2 20 14
6 3 1 0 0 10 13
7 2 0 0 0 8 12
8 0 0 0 0 6 11
9 0 0 0 0 3 9
10 0 0 0 0 1 8
'use strict';
d3.csv('movies.csv', stackedAreaChart);
function stackedAreaChart(data) {
const margin = {top: 25, left:25, bottom:25, right:50};
const width = 600 - margin.right - margin.left;
const height = 500 - margin.top - margin.bottom;
const svg = d3.select('body').append('svg')
.attr('height', height + margin.top + margin.bottom)
.attr('width', width + margin.right + margin.left)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.right + ')');
const xScale = d3.scaleLinear().domain([1, 10]).range([0, width - margin.right]);
const yScale = d3.scaleLinear().domain([0, 55]).range([height - 5, 0]);
const fillScale = d3.scaleOrdinal()
.domain(['titanic', 'avatar', 'akira', 'frozen', 'deliverance', 'avengers'])
.range(['coral', 'skyblue', 'olive', 'sandybrown', 'royalblue', '#41a368']);
const xAxis = d3.axisBottom().scale(xScale)
.tickValues([1,2,3,4,5,6,7,8,9,10])
.tickSize(height);
svg.append('g').attr('class', 'xAxis').call(xAxis)
const yAxis = d3.axisLeft().scale(yScale)
.tickSize(-(width - margin.right));
svg.append('g').attr('class', 'yAxis').call(yAxis);
// if you only want to have the upper portion, use d3.line().
// Create lines
Object.keys(data[0]).forEach(key => {
if (key !== 'day') {
var movieArea = d3.area()
.x(d => xScale(d.day))
.y0(d => yScale(simpleStacking(d, key) - d[key]))
.y1(d => yScale(simpleStacking(d, key)))
.curve(d3.curveBasis);
svg.append('path')
.style('id', key + 'Area')
.attr('d', movieArea(data))
.attr('fill', fillScale(key))
.attr('stroke', 'black')
.attr('stroke-width', 1)
.attr('fill-opacity', .75);
}
})
function simpleStacking(lineData, lineKey) {
var newHeight = 0;
Object.keys(lineData).every(key => {
if (key !== 'day') {
newHeight += parseInt(lineData[key]);
if (key === lineKey) {
return false
}
}
return true
})
return newHeight
};
var legendA = d3.legendColor().scale(fillScale);
d3.select('svg').append('g')
.attr('transform', 'translate(' + (width - margin.left) + ',' + margin.top + ')')
.call(legendA);
legendA.shapePadding(60)
.shapeHeight(5)
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment