Skip to content

Instantly share code, notes, and snippets.

@dogobox
Forked from mbostock/.block
Last active April 29, 2016 09:17
Show Gist options
  • Save dogobox/3a070ae6ac523827c09e to your computer and use it in GitHub Desktop.
Save dogobox/3a070ae6ac523827c09e to your computer and use it in GitHub Desktop.
Multi Series Graph with Inline Labels

This is an implementation of Ann K. Emery’s technique of placings labels directly on top of a line in D3 4.0 Alpha.

This is a multi series line chart in that the data is first transformed into separate arrays for each series. (The series names are dynamic and automatically derived from the columns in the TSV file, using [dsv.parse]. A label is rendered for each point in the time series. Beneath this label, a white rectangle is added, whose size and position is computed automatically using element.getBBox plus a little bit more padding.

date calls distribution
5-1-2015 2 9
5-2-2015 36 59
5-3-2015 30 34
5-4-2015 24 22
5-5-2015 30 47
5-6-2015 39 66
5-7-2015 36 50
5-8-2015 44 49
5-9-2015 33 65
5-10-2015 13 38
5-11-2015 16 20
5-12-2015 30 47
5-13-2015 45 67
5-14-2015 40 56
5-15-2015 53 46
5-16-2015 54 53
5-17-2015 21 32
5-18-2015 16 25
5-19-2015 30 58
5-20-2015 39 58
5-21-2015 44 40
5-22-2015 63 69
5-23-2015 57 40
5-24-2015 23 24
5-25-2015 28 7
5-26-2015 41 16
5-27-2015 64 83
5-28-2015 38 71
5-29-2015 62 57
5-30-2015 39 67
5-31-2015 32 46
6-1-2015 38 23
6-2-2015 39 91
6-3-2015 68 68
6-4-2015 116 68
6-5-2015 90 90
6-6-2015 79 65
6-7-2015 29 37
6-8-2015 32 20
6-9-2015 44 95
6-10-2015 40 78
6-11-2015 59 82
6-12-2015 77 71
6-13-2015 69 71
6-14-2015 44 36
6-15-2015 32 26
6-16-2015 70 71
6-17-2015 50 89
6-18-2015 65 99
6-19-2015 59 88
6-20-2015 41 82
6-21-2015 33 60
6-22-2015 16 30
6-23-2015 46 87
6-24-2015 35 76
6-25-2015 10 18
6-26-2015 5 28
6-27-2015 17 19
6-28-2015 15 24
6-29-2015 9 5
6-30-2015 35 74
7-1-2015 67 50
7-2-2015 71 74
7-3-2015 57 62
7-4-2015 61 31
7-5-2015 28 17
7-6-2015 25 27
7-7-2015 52 69
7-8-2015 27 62
7-9-2015 37 36
7-10-2015 45 73
7-11-2015 41 57
7-12-2015 27 40
7-13-2015 19 18
7-14-2015 27 42
<!DOCTYPE html>
<meta charset="utf-8">
<style>
text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.line {
fill: none;
stroke-width: 1.5px;
}
.label {
text-anchor: middle;
}
.label rect {
fill: white;
}
.label-key {
font-weight: bold;
}
</style>
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.0.0-alpha.9.min.js"></script>
<script>
var parseTime = d3.timeParse("%m-%d-%Y");
var svg = d3.select("svg");
var margin = {top: 30, right: 50, bottom: 30, left: 30},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
labelPadding = 3;
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.requestTsv("data.tsv", function(d) {
d.date = parseTime(d.date);
for (var k in d) if (k !== "date") d[k] = +d[k];
return d;
}, function(error, data) {
if (error) throw error;
var series = data.columns.slice(1).map(function(key) {
return data.map(function(d) {
return {
key: key,
date: d.date,
value: d[key]
};
});
});
var x = d3.scaleTime()
.domain([data[0].date, data[data.length - 1].date])
.range([0, width]);
var y = d3.scaleLinear()
.domain([0, d3.max(series, function(s) { return d3.max(s, function(d) { return d.value; }); })])
.range([height, 0]);
var z = d3.scaleCategory10();
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
var serie = g.selectAll(".serie")
.data(series)
.enter().append("g")
.attr("class", "serie");
serie.append("path")
.attr("class", "line")
.style("stroke", function(d) { return z(d[0].key); })
.attr("d", d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.value); }));
var label = serie.selectAll(".label")
.data(function(d) { return d; })
.enter().append("g")
.attr("class", "label")
.attr("transform", function(d, i) { return "translate(" + x(d.date) + "," + y(d.value) + ")"; });
label.append("text")
.attr("dy", ".35em")
.text(function(d) { return d.value; })
.filter(function(d, i) { return i === data.length - 1; })
.append("tspan")
.attr("class", "label-key")
.text(function(d) { return " " + d.key; });
label.append("rect", "text")
.datum(function() { return this.nextSibling.getBBox(); })
.attr("x", function(d) { return d.x - labelPadding; })
.attr("y", function(d) { return d.y - labelPadding; })
.attr("width", function(d) { return d.width + 2 * labelPadding; })
.attr("height", function(d) { return d.height + 2 * labelPadding; });
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment