block by pnavarrc 12e05466d99b99dbee85

Countries by Size

Full Screen

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>

    // Set the dimensions of the map
    var width  = 960,
        height = 960,
        nrows  = 12,
        ncols  = 12,
        dx = width / ncols,
        dy = height / nrows;

    // Create a selection for the container div and append the svg element
    var div = d3.select('#map-container'),
        svg = div.append('svg');

    // Set the size of the SVG element
    svg
      .attr('width', width)
      .attr('height', height);

    // Create and configure a geographic projection
    var projection = d3.geo.mercator()
      .scale(90);

    // Create and configure a path generator
    var pathGenerator = d3.geo.path()
      .projection(projection);

    // Create and configure the graticule generator (one line every 20 degrees)
    var graticule = d3.geo.graticule();

    // Create scales to position countries in a grid
    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);

    // Retrieve the geographic data asynchronously
    d3.json('countries.geojson', function(err, data) {

      // Throw errors on getting or parsing the file
      if (err) { throw err; }

      var countries = data.features;

      // Compute each country’s centroid and its area
      countries.forEach(function(feature) {
        feature.area   = d3.geo.area(feature);
        feature.center = d3.geo.centroid(feature);
      });

      // Sort the countries by area
      countries.sort(function(countryA, countryB) {
        return countryB.area - countryA.area;
      });

      countries = countries.slice(0, nrows * ncols);

      // Create groups to hold the countries and labels
      var grp = svg.selectAll('g.country').data(countries);

      grp.enter().append('g')
        .classed('country', true);

      // Translate the group to have a grid
      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();

      // Add the paths
      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();


      // Labels
      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

# Download and Transform the 1:50m Country Shapefiles from Natural Earth
# http://www.naturalearthdata.com/downloads/50m-cultural-vectors/

URL = http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/50m/cultural/ne_50m_admin_0_countries.zip

# Download the zip file from the Natural Earth server
ne_50m_admin_0_countries.zip:
	curl -LO $(URL)

# Unzip the shapefiles
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

# Convert the shapefiles to GeoJSON
countries.geojson: ne_50m_admin_0_countries.shp
	ogr2ogr -f GeoJSON countries.geojson ne_50m_admin_0_countries.shp

# Convert the GeoJSON file to TopoJSON
countries.topojson: countries.geojson
	topojson -p -o countries.topojson countries.geojson

# Remove source and temporary files
clean:
	rm ne_50m_admin_0_countries*