forked from devgru's block: Simple stream + interpolation, layout offset & axes
forked from anonymous's block: Simple stream + interpolation, layout offset & axes
license: mit |
forked from devgru's block: Simple stream + interpolation, layout offset & axes
forked from anonymous's block: Simple stream + interpolation, layout offset & axes
<!DOCTYPE html> | |
<meta charset='utf-8'> | |
<style> | |
body { font: 10px sans-serif; } | |
p { font: 12px helvetica; } | |
.axis path, .axis line { | |
fill: none; | |
stroke: #000; | |
stroke-width: 2px; | |
shape-rendering: crispEdges; | |
} | |
</style> | |
<body> | |
<script src='http://d3js.org/d3.v4.js'></script> | |
<script src='http://d3js.org/colorbrewer.v1.js'></script> | |
<script> | |
var parse = d3.timeParse('%m/%d/%y') | |
var margin = {top: 20, right: 40, bottom: 30, left: 30} | |
var width = 600 - margin.left - margin.right | |
var height = 400 - margin.top - margin.bottom | |
var x = d3.scaleTime().range([0, width]) | |
var y = d3.scaleLinear().range([height - 10, 0]) | |
var color = d3.scaleOrdinal().range(colorbrewer['Blues'][6]) | |
var xAxis = d3.axisBottom() | |
.scale(x) | |
var yAxis = d3.axisLeft() | |
.scale(y) | |
var yAxis2 = d3.axisRight() | |
.scale(y) | |
var area = d3.area() | |
.curve(d3.curveCardinalOpen) | |
.x(function(d) { return x(d.date) }) | |
.y0(function(d) { return y(d.coords[0]) }) | |
.y1(function(d) { return y(d.coords[1]) }) | |
var svg = d3.select('body') | |
.append('svg') | |
.attr('width', width + margin.left + margin.right) | |
.attr('height', height + margin.top + margin.bottom) | |
.append('g') | |
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') | |
function prepareData(data) { | |
var nestedByDate = d3.nest() | |
.key(function(d) { return d.date }) | |
.entries(data); | |
var nestedByKey = d3.nest() | |
.key(function(d) { return d.key }) | |
.entries(data); | |
var keys = nestedByKey.map(function(d) { return d.key }); | |
var stack = d3.stack() | |
.offset(d3.stackOffsetSilhouette) // wiggle | |
.value(function(d, k) { | |
return d.values.filter(function(d) { | |
return d.key == k; | |
})[0].value | |
}) | |
.keys(keys) | |
var result = stack(nestedByDate) | |
nestedByKey.forEach(function(d, i) { | |
d.values.forEach(function(v, j) { | |
v.coords = result[i][j] | |
}) | |
}); | |
return nestedByKey; | |
} | |
d3.csv('https://d3.devg.ru/data/stream.csv', function(d) { | |
d.date = parse(d.date) | |
d.value = Number(d.value) | |
return d | |
}, function (data) { | |
var layers = prepareData(data) | |
x.domain(d3.extent(data, function (d) { return d.date })) | |
y.domain([ | |
d3.min(data, function (d) { return d.coords[0] }), | |
d3.max(data, function (d) { return d.coords[1] }) | |
]) | |
svg.selectAll('.layer') | |
.data(layers) | |
.enter().append('path') | |
.attr('class', 'layer') | |
.attr('d', function (d) { | |
return area(d.values) }) | |
.style('fill', function (d, i) { return color(i) }) | |
svg.append('g') | |
.attr('class', 'x axis') | |
.attr('transform', 'translate(0,' + height + ')') | |
.call(xAxis) | |
svg.append('g') | |
.attr('class', 'y axis') | |
.attr('transform', 'translate(' + width + ', 0)') | |
.call(yAxis2) | |
svg.append('g') | |
.attr('class', 'y axis') | |
.call(yAxis) | |
}) | |
</script> |