index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Countries by Size</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
</head>
<body>
<style>
body {
margin: 20px;
}
.country {
fill: #A0C55F;
}
.label {
text-transform: uppercase;
text-anchor: middle;
font-size: 8px;
font-family: 'Helvetica Neue', Helvetica, sans-serif;
fill: #0D6759;
}
</style>
<div id="map-container"></div>
<script>
var width = 960,
height = 960,
nrows = 12,
ncols = 12,
dx = width / ncols,
dy = height / nrows;
var div = d3.select('#map-container'),
svg = div.append('svg');
svg
.attr('width', width)
.attr('height', height);
var projection = d3.geo.mercator()
.scale(90);
var pathGenerator = d3.geo.path()
.projection(projection);
var graticule = d3.geo.graticule();
var rowScale = d3.scale.ordinal()
.domain(d3.range(0, ncols))
.rangePoints([0, width], 1);
var colScale = d3.scale.ordinal()
.domain(d3.range(0, nrows))
.rangePoints([0, height], 1);
d3.json('countries.geojson', function(err, data) {
if (err) { throw err; }
var countries = data.features;
countries.forEach(function(feature) {
feature.area = d3.geo.area(feature);
feature.center = d3.geo.centroid(feature);
});
countries.sort(function(countryA, countryB) {
return countryB.area - countryA.area;
});
countries = countries.slice(0, nrows * ncols);
var grp = svg.selectAll('g.country').data(countries);
grp.enter().append('g')
.classed('country', true);
grp.attr('transform', function(d, i) {
var row = Math.floor(i % ncols),
col = Math.floor(i / ncols);
return 'translate(' + [rowScale(row), colScale(col)] + ')';
});
grp.exit().remove();
var path = grp.selectAll('path.country')
.data(function(d) { return [d]; });
path.enter().append('path')
.classed('country', true);
path
.attr('d', function(d) {
projection
.translate([0, 0])
.rotate([-d.center[0], -d.center[1]]);
return pathGenerator(d);
});
path.exit().remove();
var labels = grp.selectAll('text.label')
.data(function(d) { return [d]; });
labels.enter().append('text')
.classed('label', true);
labels
.attr('y', -0.25 * dy)
.text(function(d) {
var name = d.properties.admin,
abbrev = d.properties.abbrev;
return name.length < 10 ? name : abbrev;
});
labels.exit().remove();
});
</script>
</body>
</html>
Makefile
URL = http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/50m/cultural/ne_50m_admin_0_countries.zip
ne_50m_admin_0_countries.zip:
curl -LO $(URL)
ne_50m_admin_0_countries.shp: ne_50m_admin_0_countries.zip
unzip ne_50m_admin_0_countries.zip
touch ne_50m_admin_0_countries.shp
countries.geojson: ne_50m_admin_0_countries.shp
ogr2ogr -f GeoJSON countries.geojson ne_50m_admin_0_countries.shp
countries.topojson: countries.geojson
topojson -p -o countries.topojson countries.geojson
clean:
rm ne_50m_admin_0_countries*