Built with blockbuilder.org
xxxxxxxxxx
<head>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
#chart {
margin-left: -40px;
height: 506px;
}
text {
font: 10px sans-serif;
}
.dot {
stroke: #000;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.label {
fill: #777;
}
.year.label {
font: 500 196px "Helvetica Neue";
fill: #ddd;
}
.year.label.active {
fill: #aaa;
}
.overlay {
fill: none;
pointer-events: all;
cursor: ew-resize;
}
body {
margin: 0;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
</style>
</head>
<body>
<script>
// accessors that specify the four dimensions of data to visualize
function x(d) { return d.income; }
function y(d) { return d.lifeExpectancy; }
function radius(d) { return d.population; }
function color(d) { return d.region; }
function key(d) { return d.name; }
// dimensions
var margin = { top: 19.5, right: 19.5, bottom: 19.5, left: 39.5 }
var width = 960 - margin.right
var height = 500 - margin.top - margin.bottom
// scales
//so all of these are just hard-coded in, which I believe is not what we're supposed to do
var xScale = d3.scaleLog()
.domain([300, 1e5])
.range([0, width])
var yScale = d3.scaleLinear()
.domain([10,85])
.range([height, 0])
var radiusScale = d3.scaleSqrt()
.domain([0, 5e8])
.range([0, 40])
var colorScale = d3.scaleOrdinal(d3.schemeCategory10);
// axes
var xAxis = d3.axisBottom()
.scale(xScale)
.ticks(12, d3.format(",d"))
var yAxis = d3.axisLeft()
.scale(yScale)
// create the SVG container
var svg = d3.select('#chart').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 + ")");
// append the axes
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// label the axes
svg.append("text")
.attr("class", "x label")
.attr("text-anchor", "end")
.attr("x", width)
.attr("y", height - 6)
.text("income per capita, inflation-adjusted (dollars)");
svg.append("text")
.attr("class", "y label")
.attr("text-anchor", "end")
.attr("y", 6)
.attr("dy", ".75em")
.attr("transform", "rotate(-90)")
.attr("life expectancy (years)");
// add the year label
var label = svg.append("text")
.attr("class", "year label")
.attr("text-anchor", "end")
.attr("y", height - 24)
.attr("x", width)
.text(1800);
// load the data
d3.json("nations.json", function(nations) {
// a bisector -- what is this?
var bisect = d3.bisector(function(d) { return d[0]; });
// make dots. initialize the year at 1800. set colors
var dot = svg.append("g")
.attr("class", "dots")
.selectAll(".dot")
.data(interpolateData(1800))
.enter().append("circle")
.attr("class", "dot")
.style("fill", function(d) { return colorScale(color(d)) } )
.call(position)
.sort(order);
// add a title
dot.append("title")
.text(function(d) { return d.name; });
// add an overlay for the year label
// start a transition that interpolates the data based on year
svg.transition()
.duration(30000) // how did he arrive at this figure?
.ease(d3.easeLinear)
.tween("year", tweenYear)
.on("end", enableInteraction);
// assigns coordinates to the dots
function position(dot) {
dot .attr("cx", function(d) { return xScale(x(d)) })
.attr("cy", function(d) { return yScale(y(d)) })
.attr("r", function(d) { return radiusScale(radius(d)) });
}
// creates sort order to make the smallest dots show up on top of the big ones
function order(a, b) {
return radius(b) - radius(a);
}
// create mouseover to change the year
// function enableInteraction() {
// var yearScale = d3.scaleLinear()
// .domain([1800, 2009])
// .range([box.x + 10, box.x + box.width - 10 ])
// .clamp(true);
})
// tweens the entire chart
// updates the display to show the specified year
// interpolates the dataset for the given fractional year
function interpolateData(year) {
return nations.map(function(d) {
return {
name: d.name,
region: d.region,
income: interpolateValues(d.income, year),
population: interpolateValues(d.population, year),
lifeExpectancy: interpolateValues(d.lifeExpectancy, year)
};
});
}
// finds the value for the specified year
function interpolateValues(values, year) {
var i = bisect.left(values, year, 0, values.length - 1),
a = values[i];
if (i > 0) {
var b = values[i - 1],
t = (year - a[0]) / (b[0] - a[0]);
return a[1] * (1 - t) + b[1] * t;
}
return a[1];
};
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js