|
// Generated by CoffeeScript 1.10.0 |
|
(function() { |
|
var CONTINENTS, color, contents, graticule, height, lod, path, projection, radius, 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 = ['North America', 'Africa', 'South America', 'Asia', 'Europe', 'Oceania', 'Seven seas (open ocean)']; |
|
|
|
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([16, 13.8]).scale(1.3 * width / (2 * Math.PI)).translate([width / 2, height / 2]); |
|
|
|
path = d3.geoPath(projection); |
|
|
|
graticule = d3.geoGraticule(); |
|
|
|
radius = d3.scaleSqrt().range([0, 65]); |
|
|
|
simulation = d3.forceSimulation().force('collision', d3.forceCollide(function(d) { |
|
return d.r + 0.35; |
|
})).force('attract', d3.forceAttract().target(function(d) { |
|
return [d.foc_x, d.foc_y]; |
|
})); |
|
|
|
color = d3.scaleOrdinal(d3.schemeCategory10).domain(CONTINENTS); |
|
|
|
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'; |
|
})); |
|
contents.append('path').attrs({ |
|
"class": 'land', |
|
d: path(land) |
|
}); |
|
countries_data.forEach(function(d) { |
|
var subpolys; |
|
if (d.geometry.type === 'Polygon') { |
|
return d.main = d; |
|
} else if (d.geometry.type === 'MultiPolygon') { |
|
subpolys = []; |
|
d.geometry.coordinates.forEach(function(p) { |
|
var sp; |
|
sp = { |
|
coordinates: p, |
|
properties: d.properties, |
|
type: 'Polygon' |
|
}; |
|
sp.area = d3.geoArea(sp); |
|
return subpolys.push(sp); |
|
}); |
|
return d.main = subpolys.reduce((function(a, b) { |
|
if (a.area > b.area) { |
|
return a; |
|
} else { |
|
return b; |
|
} |
|
}), subpolys[0]); |
|
} |
|
}); |
|
return d3.csv('population.csv', function(data) { |
|
var bubbles, en_bubbles, en_labels, i, index, j, labels, population_data, ref; |
|
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'] |
|
}); |
|
} |
|
}); |
|
radius.domain([ |
|
0, d3.max(population_data, function(d) { |
|
return d.value; |
|
}) |
|
]); |
|
population_data.forEach(function(d) { |
|
return d.r = radius(d.value); |
|
}); |
|
population_data.forEach(function(d) { |
|
d.centroid = projection(d3.geoCentroid(d.country.main)); |
|
d.x = d.centroid[0]; |
|
d.y = d.centroid[1]; |
|
d.foc_x = d.centroid[0]; |
|
return d.foc_y = d.centroid[1]; |
|
}); |
|
bubbles = zoomable_layer.selectAll('.bubble').data(population_data); |
|
en_bubbles = bubbles.enter().append('circle').attrs({ |
|
"class": 'bubble', |
|
r: function(d) { |
|
return d.r; |
|
}, |
|
fill: function(d) { |
|
return color(d.parent); |
|
} |
|
}); |
|
en_bubbles.append('title').text(function(d) { |
|
return d.country.properties.name_long + "\nPopulation: " + (d3.format(',')(d.value)); |
|
}); |
|
labels = zoomable_layer.selectAll('.label').data(population_data); |
|
en_labels = labels.enter().append('g').attrs({ |
|
"class": 'label' |
|
}); |
|
en_labels.append('text').text(function(d) { |
|
return d.country.properties.name_long; |
|
}).attrs({ |
|
dy: '0.35em' |
|
}); |
|
lod(1); |
|
simulation.nodes(population_data).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.x + "," + d.y + ")"; |
|
} |
|
}); |
|
return en_labels.attrs({ |
|
transform: function(d) { |
|
return "translate(" + d.x + "," + d.y + ")"; |
|
} |
|
}); |
|
}); |
|
}); |
|
|
|
lod = function(z) { |
|
return zoomable_layer.selectAll('.label').classed('hidden', function(d) { |
|
return d.r < 23 / z; |
|
}); |
|
}; |
|
|
|
}).call(this); |