|
// Generated by CoffeeScript 1.10.0 |
|
(function() { |
|
var CONTINENTS, color, contents, graticule, height, lod, pack, path, projection, simulation, svg, width, zoom, zoomable_layer; |
|
|
|
svg = d3.select('body').append('svg'); |
|
|
|
width = d3.select('svg').node().getBoundingClientRect().width; |
|
|
|
height = d3.select('svg').node().getBoundingClientRect().height; |
|
|
|
CONTINENTS = [ |
|
{ |
|
id: 'North America', |
|
centroid: [-100.258219, 42.393044] |
|
}, { |
|
id: 'Africa', |
|
centroid: [14.313831, 4.467357] |
|
}, { |
|
id: 'South America', |
|
centroid: [-68.083970, -13.071758] |
|
}, { |
|
id: 'Asia', |
|
centroid: [116.019485, 30.377321] |
|
}, { |
|
id: 'Europe', |
|
centroid: [13.559762, 50.671550] |
|
}, { |
|
id: 'Oceania', |
|
centroid: [151.026997, -32.147138] |
|
}, { |
|
id: 'Seven seas (open ocean)', |
|
centroid: [64.587828, -26.307320] |
|
} |
|
]; |
|
|
|
zoomable_layer = svg.append('g'); |
|
|
|
zoom = d3.zoom().scaleExtent([-Infinity, Infinity]).on('zoom', function() { |
|
zoomable_layer.attrs({ |
|
transform: d3.event.transform |
|
}); |
|
zoomable_layer.selectAll('.label > text').attrs({ |
|
transform: "scale(" + (1 / d3.event.transform.k) + ")" |
|
}); |
|
return lod(d3.event.transform.k); |
|
}); |
|
|
|
svg.call(zoom); |
|
|
|
projection = d3.geoWinkel3().rotate([0, 0]).center([20, 16]).scale(1.2 * width / (2 * Math.PI)).translate([width / 2, height / 2]); |
|
|
|
path = d3.geoPath(projection); |
|
|
|
CONTINENTS.forEach(function(d) { |
|
return d.centroid = projection(d.centroid); |
|
}); |
|
|
|
graticule = d3.geoGraticule(); |
|
|
|
pack = d3.pack().size([1.2 * width, 1.2 * height]).padding(3); |
|
|
|
CONTINENTS.forEach(function(d) { |
|
return d.force = {}; |
|
}); |
|
|
|
simulation = d3.forceSimulation().force('collision', d3.forceCollide(function(d) { |
|
return d.r; |
|
}).strength(0.01)).force('attract', d3.forceAttract().target(function(d) { |
|
return [d.foc_x, d.foc_y]; |
|
}).strength(0.5)); |
|
|
|
color = d3.scaleOrdinal(d3.schemeCategory10).domain(CONTINENTS.map(function(d) { |
|
return d.id; |
|
})); |
|
|
|
contents = zoomable_layer.append('g'); |
|
|
|
d3.json('ne_50m_admin_0_countries.topo.json', function(geo_data) { |
|
var countries_data, land; |
|
countries_data = topojson.feature(geo_data, geo_data.objects.countries).features; |
|
land = topojson.merge(geo_data, geo_data.objects.countries.geometries.filter(function(d) { |
|
return d.properties.continent !== 'Antarctica'; |
|
})); |
|
CONTINENTS.forEach(function(d) { |
|
d.force.x = d.centroid[0]; |
|
d.force.y = d.centroid[1]; |
|
d.force.foc_x = d.centroid[0]; |
|
return d.force.foc_y = d.centroid[1]; |
|
}); |
|
contents.append('path').attrs({ |
|
"class": 'land', |
|
d: path(land) |
|
}); |
|
return d3.csv('population.csv', function(data) { |
|
var bubbles, en_bubbles, en_labels, i, index, j, labels, population_data, ref, root; |
|
index = {}; |
|
data.forEach(function(d) { |
|
return index[d['Country Code']] = d; |
|
}); |
|
population_data = []; |
|
countries_data.forEach(function(d) { |
|
if (d.properties.iso_a3 in index) { |
|
return population_data.push({ |
|
id: d.properties.iso_a3, |
|
parent: d.properties.continent, |
|
country: d, |
|
value: +index[d.properties.iso_a3]['2016'] |
|
}); |
|
} |
|
}); |
|
population_data.push({ |
|
id: "root", |
|
parent: "" |
|
}); |
|
CONTINENTS.forEach(function(d) { |
|
return population_data.push({ |
|
id: d.id, |
|
parent: "root", |
|
d: d |
|
}); |
|
}); |
|
root = (d3.stratify().id(function(d) { |
|
return d.id; |
|
}).parentId(function(d) { |
|
return d.parent; |
|
}))(population_data); |
|
root.sum(function(d) { |
|
return d.value; |
|
}).sort(function(a, b) { |
|
return b.value - a.value; |
|
}); |
|
pack(root); |
|
root.eachBefore(function(d) { |
|
if (d.parent != null) { |
|
d.relx = d.x - d.parent.x; |
|
return d.rely = d.y - d.parent.y; |
|
} else { |
|
d.relx = d.x; |
|
return d.rely = d.y; |
|
} |
|
}); |
|
root.eachBefore(function(d) { |
|
if ((d.parent != null) && d.parent.id === 'root') { |
|
return d.data.d.force.r = d.r; |
|
} |
|
}); |
|
bubbles = zoomable_layer.selectAll('.bubble').data(root.leaves()); |
|
en_bubbles = bubbles.enter().append('circle').attrs({ |
|
"class": 'bubble', |
|
r: function(d) { |
|
return d.r; |
|
}, |
|
fill: function(d) { |
|
return color(d.parent.id); |
|
} |
|
}); |
|
en_bubbles.append('title').text(function(d) { |
|
return d.data.country.properties.name_long + "\nPopulation: " + (d3.format(',')(d.value)); |
|
}); |
|
labels = zoomable_layer.selectAll('.label').data(root.leaves()); |
|
en_labels = labels.enter().append('g').attrs({ |
|
"class": 'label' |
|
}); |
|
en_labels.append('text').text(function(d) { |
|
return d.data.country.properties.name_long; |
|
}).attrs({ |
|
dy: '0.35em' |
|
}); |
|
lod(1); |
|
simulation.nodes(CONTINENTS.map(function(d) { |
|
return d.force; |
|
})).stop(); |
|
for (i = j = 0, ref = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) { |
|
simulation.tick(); |
|
} |
|
en_bubbles.attrs({ |
|
transform: function(d) { |
|
return "translate(" + (d.relx + d.parent.data.d.force.x) + "," + (d.rely + d.parent.data.d.force.y) + ")"; |
|
} |
|
}); |
|
return en_labels.attrs({ |
|
transform: function(d) { |
|
return "translate(" + (d.relx + d.parent.data.d.force.x) + "," + (d.rely + d.parent.data.d.force.y) + ")"; |
|
} |
|
}); |
|
}); |
|
}); |
|
|
|
lod = function(z) { |
|
zoomable_layer.selectAll('.label').classed('hidden', function(d) { |
|
return d.r < 23 / z; |
|
}); |
|
return zoomable_layer.selectAll('.land').attrs({ |
|
opacity: 1 / z |
|
}); |
|
}; |
|
|
|
}).call(this); |