block by pnavarrc 62047b5638d624cfa9cb

Automatic Scaling Features with D3

Full Screen

Automatic Scaling Features with D3

Thumbnail

Use d3.geo.bounds and d3.geo.distance to compute an approximate scale to display a complete feature.

References

index.html

<html>
<head>
    <title>Automatic Scaling Features with D3</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>
        .country {
            fill: #bbb;
            stroke: #eee;
            stroke-width: 1;
        }
    </style>

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

    <script>

        var width  = 600,
            height = 600;

        // Create the geographic projection
        var projection = d3.geo.mercator()
            .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);

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

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

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

            // Construct a feature for South America
            // -------------------------------------

            // Filter out the countries outside South America
            var southAmerica = features.filter(function(country) {
                return country.properties.continent === 'South America';
            });

            var southAmericaFeature = {
                type: 'FeatureCollection',
                features: southAmerica
            };

            // Compute the feature bounds and centroid
            var bounds = d3.geo.bounds(southAmericaFeature),
                center = d3.geo.centroid(southAmericaFeature);

            // Compute the angular distance between bound corners
            var distance = d3.geo.distance(bounds[0], bounds[1]),
                scale = height / distance / Math.sqrt(2);

            // Update the projection scale and centroid
            projection.scale(scale).center(center);

            // Draws the countries
            var countries = grp.selectAll('path.country').data([southAmericaFeature]);
            countries.enter().append('path').classed('country', true);
            countries.attr('d', pathGenerator);
            countries.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 -o countries.topojson countries.json

clean:
	rm ne_50m_admin_0_countries*
	rm countries.json