xxxxxxxxxx
<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>
https://cdnjs.cloudflare.com/ajax/libs/d3/5.5.0/d3.min.js