A series of sparklines representing the gross national income per capita of 33 low-income countries (there are 36 such countries in total). The data come from the World Bank, via Gapminder, and can be found here
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
font-family: Helvetica;
font-size: 12px;
}
.top-div {
float: left;
width: 200px;
height: 20px;
}
#year-div {
border-bottom: solid 1px;
font-weight: bold;
width:100px;
}
#chart-container {
margin-top: 10px;
clear: both;
}
path {
fill: none;
stroke: darkmagenta;
stroke-width: 2.5px;
}
line {
fill: none;
stroke: #666;
stroke-width: 1px;
shape-rendering: crispEdges;
}
.overlay {
fill: none;
pointer-events: all;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.js"></script>
<script>
var margin = {top: 0, right: 0, bottom: 0, left: 120};
width = 200 - margin.left - margin.right,
height = 20 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width])
var y = d3.scale.linear()
.range([height, 0])
var line = d3.svg.line()
.x(function(d) { return x(d.year); })
.y(function(d) { return y(d.value); });
format = d3.format("$0");
var bisectYear = d3.bisector(function(d) { return d.year; }).left;
function compare(a,b) {
if (a.key < b.key)
return -1;
if (a.key > b.key)
return 1;
return 0;
}
body = d3.select("body")
body.append("div")
.attr("class", "top-div")
year = body.append("div")
.attr("class", "top-div")
.attr("id", "year-div")
.append("svg")
.attr("width", 100)
.attr("height", 20)
.append("text")
.attr("text-anchor", "middle")
.attr("x", 50)
.attr("y", 15)
.text("2012")
container = body.append("div")
.attr("id", "chart-container")
var myData;
d3.csv("data.csv", function(error, data) {
data.forEach(function(d) {
d.value = +d.value;
d.year = +d.year;
})
x.domain(d3.extent(data, function(d) { return d.year; }))
y.domain([0, d3.max(data, function(d) { return d.value; })])
var nested = d3.nest()
.key(function(d) { return d.Country; })
.entries(data)
nested = nested.sort(compare)
var svg = container.append("svg")
.attr("width", 450)
.attr("height", nested.length*(height + margin.top + margin.bottom))
.append("g")
.attr("transform", "translate(" + margin.left + ",0)")
var plots = svg.selectAll("g")
.data(nested)
.enter().append("g")
.attr("transform", function(d, i) {
yAdjust = i*(height + margin.top + margin.bottom)
return "translate(0" + "," + yAdjust + ")"
});
plots.append("path")
.datum(function(d) {
return d.values;
})
.attr("class", "line")
.attr("d", line)
plots.append("text")
.attr("x", -5)
.attr("y", height)
.text(function(d) { return d.key; })
.attr("text-anchor", "end")
currentVal = plots.append("text")
.attr("class", "income")
.attr("x", 250 - margin.left)
.attr("y", height)
.attr("text-anchor", "middle")
.text(function(d) {
filtered = d.values.filter(function(d) {return d.year == 2012})
return format(Math.round(filtered[0].value))
})
var crosshair = svg.append("line")
.attr("display","none")
.attr("x1",0)
.attr("x2",0)
.attr("y1",0)
.attr("y2",nested.length*(height + margin.top + margin.bottom))
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", nested.length*(height + margin.top + margin.bottom))
.on("mousemove", mousemove)
.on("mouseenter", function() {crosshair.attr("display", null)})
.on("mouseleave", function() {
crosshair.attr("display", "none")
console.log("you're out")
})
function mousemove() {
var x0 = Math.round(x.invert(d3.mouse(this)[0]))
currentVal.text(function(d) {
filtered = d.values.filter(function(d) {return d.year == x0})
if (filtered[0])
return format(Math.round(filtered[0].value))
else
return "No data"
})
year.text(x0)
crosshair.attr("transform","translate(" + Math.round(x(x0)) + ",0)")
}
})
</script>
Modified http://d3js.org/d3.v3.js to a secure url
https://d3js.org/d3.v3.js