|
<!DOCTYPE html> |
|
<head> |
|
|
|
<meta charset="utf-8"> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> |
|
<style> |
|
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } |
|
svg { |
|
border: 1px solid orange; |
|
} |
|
#info { |
|
position: absolute; |
|
right: 0; |
|
top: 40px; |
|
border: 1px solid black; |
|
min-width: 100px; |
|
min-height: 50px; |
|
} |
|
</style> |
|
</head> |
|
|
|
<body> |
|
<div id="chart"></div> |
|
<div id="info"></div> |
|
<script> |
|
|
|
function toNumber(s) { |
|
// convert strings with spaces instead of commas into numbers |
|
var n = s.replace(/[w]/g, "") //remove any whitespace |
|
.replace(/ /g, "") //utf8 space? |
|
return +n; //convert to number |
|
} |
|
function process(d) { |
|
var processed = { |
|
|
|
start: d.Start, |
|
end: d.End, |
|
year: +d.Year, |
|
// we just deal with the price in Euros adjusted for inflation |
|
price: toNumber(d["Price EUR 2014"]), |
|
service: d.Service, |
|
route: d.route, |
|
author: d.author, |
|
comment: d.Comment, |
|
source: d.Source, |
|
} |
|
return processed; |
|
} |
|
|
|
|
|
var margin = {top: 20, right: 20, bottom: 50, left: 50}, |
|
width = 960 - margin.left - margin.right, |
|
height = 500 - margin.top - margin.bottom; |
|
|
|
var xscale = d3.scale.log() |
|
.range([0, width]); |
|
|
|
var yscale = d3.scale.ordinal() |
|
.rangeRoundBands([0, height], 0.1); |
|
|
|
d3.csv("http://enjalot.github.io/migrants/money.csv", function(err, rawdata) { |
|
|
|
var data = rawdata.map(process); |
|
d3.select("#json").text(JSON.stringify(data, null, 2)); |
|
|
|
var routes = d3.nest(data) |
|
.key(function(d) { return d.route; }) |
|
.rollup(function(leaves) { |
|
return { |
|
price: d3.sum(leaves, function(d) { return d.price; }), |
|
rows: leaves |
|
}; |
|
}) |
|
.entries(data); |
|
|
|
xscale.domain([1, d3.max(routes, function(d) { return d.values.price; })]); |
|
yscale.domain(d3.range(routes.length)); |
|
|
|
var svg = d3.select("#chart") |
|
.append("svg") |
|
.attr({ |
|
width: width + margin.left + margin.right, |
|
height: height + margin.top + margin.bottom |
|
}) |
|
.append("g") |
|
.attr("transform", "translate(" + [margin.left, margin.top] + ")"); |
|
|
|
var bars = svg.selectAll("rect.bar") |
|
.data(routes); |
|
bars.enter().append("rect") |
|
.classed("bar", true) |
|
.attr({ |
|
x: 0, |
|
y: function(d, i) { return yscale(i); }, |
|
width: function(d) { return xscale(d.values.price); }, |
|
height: yscale.rangeBand() |
|
}); |
|
|
|
bars.on("mouseover", function(d) { |
|
d3.select(this).fill("red"); |
|
var info = d3.select("#info"); |
|
info.append("h1").text(d.key); |
|
info.selectAll("div") |
|
.data(d.values.rows) |
|
.enter().append("div") |
|
.text(function(d) { return ""}) |
|
}) |
|
.on("mouseout", function(d) { |
|
d3.select("#info").selectAll("*").remove(); |
|
}); |
|
}); |
|
</script> |
|
</body> |