Created
October 18, 2018 13:12
-
-
Save tomgp/52c357df19e79c8336052c831e5e0f8a to your computer and use it in GitHub Desktop.
Stacked and stepped area chart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A | B | C | D | E | F | |
---|---|---|---|---|---|---|
1233 | 1037 | 2433 | 15167 | 5 | 33 | |
1430 | 1161 | 3134 | 15956 | 4 | 34 | |
1338 | 1258 | 2342 | 15416 | 1 | 44 | |
1304 | 1224 | 2646 | 15176 | 1 | 29 | |
1524 | 1478 | 2426 | 14601 | 2 | 31 | |
1350 | 1381 | 2732 | 15405 | 3 | 37 | |
1354 | 1534 | 2673 | 16022 | 17 | 36 | |
1375 | 1394 | 2144 | 12426 | 9 | 30 | |
1563 | 1293 | 2903 | 14888 | 7 | 42 | |
1589 | 1461 | 2664 | 17040 | 7 | 35 | |
1695 | 1466 | 3168 | 16945 | 9 | 45 | |
1309 | 1596 | 2402 | 14898 | 3 | 24 | |
1190 | 1585 | 2657 | 14506 | 3 | 31 | |
1060 | 1461 | 2154 | 15428 | 5 | 31 | |
1416 | 1570 | 2241 | 16746 | 9 | 43 | |
1329 | 1339 | 2206 | 15042 | 4 | 31 | |
1488 | 1335 | 2504 | 15362 | 6 | 34 | |
1232 | 1212 | 2473 | 16423 | 8 | 44 | |
1004 | 1459 | 2226 | 15380 | 8 | 36 | |
1002 | 1332 | 1607 | 15036 | 4 | 50 | |
1351 | 1784 | 2385 | 15898 | 2 | 43 | |
1196 | 1830 | 2503 | 16040 | 5 | 47 | |
1172 | 1923 | 2411 | 15079 | 6 | 35 | |
1050 | 2025 | 2558 | 12790 | 8 | 36 | |
1068 | 1347 | 1870 | 13899 | 13 | 31 | |
1116 | 1658 | 2180 | 12533 | 3 | 35 | |
1397 | 1471 | 2179 | 13065 | 5 | 43 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<style> | |
body{ | |
font-family:sans-serif; | |
} | |
</style> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.5.0/d3.min.js"></script> | |
</head> | |
<body> | |
<h1>stacked & stepped area chart</h1> | |
<svg></svg> | |
</body> | |
<script> | |
const categoryColours = [ | |
'rgba(255,0,0,1)', | |
'rgba(0,255,0,1)', | |
'rgba(0,0,255,1)', | |
'rgba(255,255,0,1)', | |
'rgba(255,0,255,1)', | |
'rgba(0,255,255,1)', | |
]; | |
const stackLayout = (data, properties, range, blockWidth = 30) => { | |
const rowTotals = data | |
.map(row => d3.sum(properties.map(key => row[key]))); | |
const blockScale = d3.scaleLinear() | |
.range(range) | |
.domain([0,d3.max(rowTotals)]); | |
const colorScale = d3.scaleOrdinal() | |
.range(categoryColours) | |
.domain(properties); | |
const areas = []; | |
const rowPositions = data.map((row,i) => { | |
let rowAccumulator = plotHeight; | |
properties.forEach((property) => { | |
const blockSize = blockScale(row[property]); | |
rowAccumulator -= blockSize; | |
row[property] = { | |
height: blockSize, | |
x: blockWidth * i, | |
y: rowAccumulator, | |
data: { value:row[property], property }, | |
color: colorScale(property), | |
width: blockWidth, | |
}; | |
areas.push(row[property]); | |
}); | |
return row; | |
}); | |
const areaSeparators = properties.map((property, i)=>{ | |
let xAccumulator = 0; | |
const line = []; | |
data.forEach(d => { | |
const y = d[property].y; | |
line.push({ x: xAccumulator, y }); | |
xAccumulator += blockWidth; | |
line.push({ x: xAccumulator, y }); | |
}); | |
return { | |
property, | |
line | |
}; | |
}); | |
return { | |
rects: areas, | |
lines: areaSeparators, | |
} | |
} | |
const width = 700, | |
height = 700, | |
margin = { top:20, bottom:20, left:20, right:20 }; | |
const plotWidth = width - (margin.left+margin.right); | |
const plotHeight = height - (margin.top+margin.bottom); | |
d3.select('svg') | |
.attr('width',width) | |
.attr('height',height) | |
.append('g') | |
.attr('class','plot') | |
.attr('transform',`translate(${margin.left}, ${margin.right})`); | |
d3.csv('data.csv') | |
.then((data) => { | |
const { rects, lines } = stackLayout( | |
data, | |
'A,B,C,D,E,F'.split(','), | |
[0, plotHeight], | |
plotWidth/data.length, | |
); | |
d3.select('.plot') | |
.selectAll('rect') | |
.data(rects) | |
.enter() | |
.append('rect') | |
.attr('x', d=>d.x) | |
.attr('y', d=>d.y) | |
.attr('width', d=>d.width) | |
.attr('height', d=>d.height) | |
.attr('fill', d=>d.color) | |
.attr('stroke', d=>d.color) | |
.attr('data-key', d=>d.data.property) | |
.attr('data-value', d=>d.data.value); | |
const separator = d3.line() | |
.x(d=>d.x) | |
.y(d=>d.y); | |
d3.select('.plot') | |
.selectAll('path') | |
.data(lines) | |
.enter() | |
.append('path') | |
.attr('d', d=>separator(d.line)) | |
.attr('fill','none') | |
.attr('stroke','rgba(0,0,0,1)') | |
.attr('stroke-width', 3); | |
}); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment