Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script type='text/javascript' src="https://d3js.org/d3.v4.min.js"></script>
<script type='text/javascript' src="/index.js"></script>
<title>My Page Title</title>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<style>
.container {
display: inline-block;
position: relative;
}
h2 {
font-family: 'Roboto', sans-serif;
font-size: 54px;
margin-left: 40px;
margin-bottom: 0px;
}
h1 {
font-family: 'Roboto', sans-serif;
font-size: 200px;
position: absolute;
right: 0px;
bottom: 20px;
margin-bottom: 0px;
color: #ccc;
}
</style>
</head>
<body>
<h2>The Wealth & Health of Nations</h2>
<div class='container'>
</div>
<script>
var margin = {top: 40, right: 40, bottom: 40, left: 40}
var width = 960 - margin.left - margin.right;
var height = 540 - margin.top - margin.bottom;
var loadYearMinMax = function(nations) {
var nationYears = nations.map(function(nation) {
var incomeMinMax = d3.extent(nation.income, function(i) {return i[0]})
var lifeMinMax = d3.extent(nation.lifeExpectancy, function(i) {return i[0]})
var popMinMax = d3.extent(nation.population, function(i) {return i[0]})
var allMinMax = d3.merge([incomeMinMax, lifeMinMax, popMinMax])
return d3.extent(allMinMax)
})
return d3.extent(d3.merge(nationYears))
}
// Add Year 2009 if it isn't there
var addLastYear = function(nation, attr, years) {
var last = nation[attr][nation[attr].length-1]
var firstYear = years[0]
var lastYear = years[years.length-1]
if(nation[attr].length < years.length && last[0] != lastYear) {
nation[attr].push([lastYear, last[1]])
}
return nation[attr]
}
// Add Missing Year
var interpolateAttr = function(nation, year, index, attr) {
if(index === 0 && nation[attr][0][0] != year) {
nation[attr].unshift([year, nation[attr][0][1]])
} else if(nation[attr][index] && nation[attr][index][0] != year) {
var prev = index-1;
var next = nation[attr].length-1 == index ? index : index+1;
if(nation[attr][prev] && nation[attr][next]) {
var p1 = {x: nation[attr][prev][0], y: nation[attr][prev][1]};
var p3 = {x: nation[attr][next][0], y: nation[attr][next][1]};
var p2 = {x: year};
var y = (((p2.x - p1.x)*(p3.y-p1.y))/(p3.x = p1.x))+p1.y;
nation[attr].splice(index, 0, [year, y]);
}
}
return nation[attr]
}
var buildNewNation = function(nation, index) {
return {
name: nation.name,
region: nation.region,
income: nation.income[index][1],
lifeExpectancy: nation.lifeExpectancy[index][1],
population: nation.population[index][1]
}
}
var loadRange = function() {
return {
x: [0, width],
y: [height, 0],
radius: [1, 60],
color: ['#45CCFF','#49E83E','#FFD432','#E80030','#B243FF','#080CFF']
}
}
var loadDomain = function(x, y, radius, color) {
return {
x: d3.extent(x),
y: d3.extent(y),
radius: d3.extent(radius),
color: color
}
}
var loadScale = function(domain, range) {
return {
x: d3.scaleLog().domain(domain.x).range(range.x),
y: d3.scaleLinear().domain(domain.y).range(range.y),
color: d3.scaleOrdinal().domain(domain.color).range(range.color),
radius: d3.scaleSqrt().domain(domain.radius).range(range.radius)
}
}
var drawAxes = function(scale, graph) {
var xAxis = d3.axisBottom().ticks(10, d3.format("($.0f")).scale(scale.x);
var yAxis = d3.axisLeft().scale(scale.y);
graph.append('g')
.attr('transform', 'translate(0,'+height+')')
.call(xAxis)
graph.append('g')
.call(yAxis)
}
var drawSvg = function() {
var svgWidth = width + margin.left + margin.right;
var svgHeight = height + margin.top + margin.bottom
var graph = d3.select('.container')
.append('svg')
.attr('width', svgWidth)
.attr('height', svgHeight)
.append('g')
.attr('transform', 'translate('+margin.left+','+margin.top+')')
d3.select('.container').append('h1')
return graph
}
var draw = function(graph, nations, scale) {
if(currentYear > 2009) {
return clearInterval(interval)
} else {
d3.select('h1').text(currentYear)
var t = d3.transition().duration(300);
var oldCircles = graph.selectAll('circle')
.data(nations, function(nation) {return nation.name})
if(currentYear === 1800 || currentYear === 2000) {
console.log(oldCircles)
}
oldCircles.exit().remove();
var newCircles = oldCircles.enter()
.append('circle')
.attr('cx', function(nation) {return scale.x(nation.income)})
.attr('cy', function(nation) {return scale.y(nation.lifeExpectancy)})
var circles = newCircles.merge(oldCircles)
.transition(t)
.attr('cx', function(nation) {return scale.x(nation.income)})
.attr('cy', function(nation) {return scale.y(nation.lifeExpectancy)})
.attr('r', function(nation) {return scale.radius(nation.population)})
.attr('fill', function(nation) {return scale.color(nation.region)})
.attr('fill-opacity', '0.5')
.attr('stroke-width', '1px')
.attr('stroke', function(nation) {return scale.color(nation.region)})
}
currentYear++
}
var startInterval = function(graph, nations, scale) {
return window.setInterval(function() {
draw(graph, nations[currentYear], scale)
}, 100);
}
var interval;
var currentYear = 1800
d3.json('nations.json', function(error, nations) {
var yearMinMax = loadYearMinMax(nations)
var regions = d3.nest().key(function(n) {
return n.region
}).entries(nations).map(function(r) {
return r.key
})
var years = []
var incomes = []
var populations = []
var lifeExpectancies = []
var newNations = {}
for(var year=yearMinMax[0]; year<=yearMinMax[1]; ++year) {
years.push(year)
newNations[year] = []
}
nations.forEach(function(nation) {
nation.income = addLastYear(nation, 'income', years)
nation.lifeExpectancy = addLastYear(nation, 'lifeExpectancy', years)
nation.population = addLastYear(nation, 'population', years)
years.forEach(function(year, index) {
nation.income = interpolateAttr(nation, year, index,'income')
nation.lifeExpectancy = interpolateAttr(nation, year, index,'lifeExpectancy')
nation.population = interpolateAttr(nation, year, index,'population')
var newNation = buildNewNation(nation, index)
incomes.push(newNation.income)
populations.push(newNation.population)
lifeExpectancies.push(newNation.lifeExpectancy)
newNations[year].push(newNation)
})
})
var domain = loadDomain(incomes, lifeExpectancies, populations, regions)
var range = loadRange()
var scale = loadScale(domain, range)
var graph = drawSvg()
drawAxes(scale, graph)
interval = startInterval(graph, newNations, scale)
})
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js