Population projections for EU/EFTA, 2013-2080. Data from eurostat.
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
font: 16px/1.5 georgia, serif;
-webkit-font-smoothing: antialiased;
-webkit-hyphens: auto;
padding: 20px;
}
svg { padding: 10px; }
.axis path,
.axis line {
fill: none;
stroke: gray;
shape-rendering: crispEdges;
}
.axis text {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 0.7em;
}
.x.axis path {
display: none;
}
.area {
fill: #d1e5f0;
}
.overlay {
fill: none;
pointer-events: all;
}
.label {
fill: black;
opacity: 0.6;
font-size: 1.1em !important;
}
.line {
fill: none;
stroke: #7a868c;
}
hr { opacity: 0.5; width: 98%; }
</style>
<body>
<label>
Unify scales
<input autofocus type="checkbox" id="toggle-scale">
</label>
<div class="charts"></div>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var margin = { top: 20, right: 20, bottom: 30, left: 80 },
width = 300 - margin.left - margin.right,
height = 300 - margin.bottom - margin.top;
var x = d3.time.scale().range([0, width]);
var parseDate = d3.time.format('%Y').parse;
var toggle = d3.select('#toggle-scale');
var xAxis = d3.svg.axis()
.scale(x)
.ticks(3)
.orient('bottom');
d3.tsv('projected-totals.tsv', function(error, data) {
data = parseData(data);
var totalDomain = d3.extent(d3.merge(data.map(function (d) {
return d.values.map(function (e) { return e.value; })
})));
data.forEach(function (c) {
var countryDomain = d3.extent(c.values, function (d) { return d.value; });
var y = d3.scale.linear().range([height, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.orient('left')
.ticks(5)
.tickFormat(function (d) { return d3.format(',s')(d); });
var area = d3.svg.area()
.x(function (d) { return x(d.date); })
.y0(height)
.y1(function (d) { return y(d.value); });
var line = d3.svg.line()
.x(function (d) { return x(d.date); })
.y(function (d) { return y(d.value); });
var startArea = d3.svg.area()
.x(function (d) { return x(d.date); })
.y0(height)
.y1(function (d) { return y(y.domain()[0]); });
var startLine = d3.svg.line()
.x(function (d) { return x(d.date); })
.y(height);
x.domain(d3.extent(c.values, function (d) { return d.date; }));
y.domain(countryDomain);
var svg = d3.select('.charts').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 + ')');
svg.datum(c.values, function (d) { d.date; });
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0, ' + height + ')')
.call(xAxis);
svg.append('path')
.attr('class', 'area')
.attr('d', startArea)
.transition()
.attr('d', area)
.duration(1000);
svg.append('path')
.attr('class', 'line')
.attr('d', startLine)
.transition()
.attr('d', line)
.duration(1000);
svg.append('g')
.attr('class', 'y axis')
.call(yAxis)
.append('text')
.attr('class', 'label')
.attr('x', 6)
.attr('y', 6)
.attr('dy', '.71em')
.text(c.code);
toggle.on('click.' + c.code, function () {
var newDomain = JSON.stringify(y.domain()) == JSON.stringify(countryDomain) ? totalDomain : countryDomain;
y.domain(newDomain);
svg.selectAll('g.y.axis')
.transition()
.call(yAxis)
svg.selectAll('path.area')
.transition()
.attr('d', area)
.ease('elastic')
.duration(1000);
svg.selectAll('path.line')
.transition()
.attr('d', line)
.ease('elastic')
.duration(1000);
});
});
})
function parseData(data) {
return data.map(function (row) {
var map = d3.map(row);
var parts = map.get('key').split(',');
var code = parts[2];
var sex = parts[1];
map.remove('key');
var values = map.entries().map(function (e) {
return {date: parseDate(e.key.trim()), value: +e.value}
})
return {
code: code,
sex: sex,
values: values
};
}).filter(function (d) { return d.sex === 'T' && d.code != 'EU28' })
}
</script>
</body>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js