block by pnavarrc 14ed098d4072be2715db

Square Countries

Full Screen

Countries as Squares

Thumbnail

Small experiment of showing each country as a square. The center of each square is computed projecting the centroid of each feature, the (projected) area of each country is computed using the D3 path.area method.

References

index.html

<html>
<head>
    <title>Countries as Squares</title>

    <script charset="utf-8" src="//d3js.org/d3.v3.min.js"></script>
    <script charset="utf-8" src="//d3js.org/topojson.v1.min.js"></script>

    <style>
        body {
            background-color: #222;
        }

        path.country {
            fill: #333;
        }

        rect.country {
            stroke: #5EFFEF;
            stroke-opacity: 0.9;
            stroke-width: 1;
            fill: #5EFFEF;
            fill-opacity: 0.05;
        }

        rect.highlighted {
            fill-opacity: 0.6;
            stroke-width: 1;
            stroke: #78fff2;
        }

        .country-label {
            pointer-events: none;
            font-family: Arial, sans-serif;
            font-size: 21px;
            fill: #5EFFEF;
        }
    </style>

</head>
<body>
    <div id="map"></div>

    <script>

        var width  = 800,
            height = 400;

        // Create the geographic projection
        var projection = d3.geo.equirectangular()
            .scale(width / (2 * Math.PI))
            .translate([width / 2, height / 2]);

        // Configure the path generator
        var pathGenerator = d3.geo.path()
            .projection(projection);

        var div = d3.select('#map'),
            svg = div.append('svg'),
            grp = svg.append('g');

        svg.attr('width', width).attr('height', height + 200);
        grp.attr('transform', 'translate(' + [0, 100] + ')');

        d3.json('countries.topojson', function(error, data) {

            if (error) {
                console.error(error);
                throw error;
            }

            var geojson = topojson.feature(data, data.objects.countries).features;

            // Compute the projected centroid, area and length of the side
            // of the squares.
            geojson.forEach(function(d) {
                d.centroid = projection(d3.geo.centroid(d));
                d.area = d3.geo.path().projection(projection).area(d);
                d.side = Math.sqrt(d.area);
            });

            // Sort the features by projected area
            geojson.sort(function(a, b) { return b.area - a.area; });

            var countries = grp.selectAll('path.country').data(geojson);

            countries.enter().append('path').classed('country', true);
            countries.attr('d', pathGenerator);
            countries.exit().remove();

            // Squares
            var squares = grp.selectAll('rect.country').data(geojson);
            squares.enter().append('rect').classed('country', true);
            squares
                .attr('x', function(d) { return d.centroid[0] - d.side / 2; })
                .attr('y', function(d) { return d.centroid[1] - d.side / 2; })
                .attr('width', function(d) { return d.side; })
                .attr('height', function(d) { return d.side; });
            squares.on('mouseover', function(d) {

                    // Highlight on mouse over
                    d3.select(this).classed('highlighted', true);

                    grp.append('text')
                        .classed('country-label', true)
                        .attr('x', 20)
                        .attr('y', 0)
                        .text(d.properties.admin);
                })
                .on('mouseout', function(d) {
                    d3.select(this).classed('highlighted', false);
                    grp.selectAll('text.country-label').remove();
                });

            squares.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.json: ne_50m_admin_0_countries.shp
	ogr2ogr -f GeoJSON countries.json ne_50m_admin_0_countries.shp

countries.topojson: countries.json
	topojson -p admin -o countries.topojson countries.json

clean:
	rm ne_50m_admin_0_countries*
	rm countries.json