D3: Basemap With Topojson

D3 Tutorials : Example 003 ( bl.ock | gist )

To get geodata to render properly in D3, there are some key properties you will have to define first:

  • Canvas dimensions (width, height)
  • SVG Canvas
  • Projection
  • Path
  • path/to/geodata.file

Typically geodata has come in geojson format (an extension of json). It has been an incredibly useful format for quickly rendering geographic data on the web. It’s fast, to be sure, but D3 has taken the geojson one step further and now we have topojson (learn about geojson > topojson conversion [coming soon]), which has significantly decreased file size for polygonal geographic data. These tutorials will use topojson format for land basemap rendering. Be sure to add the topojson extension library to your header after you have loaded the d3 library:

<script src="http://d3js.org/topojson.v1.min.js"></script>

There are some variables in here that will definitely require some playing around with depending on what you are trying to show. One of the best things d3.geo has going for it is the defining of projections. This gives d3 (and svg in general) an advantage to normal tile-based mapping because you can display different parts of the world in the geographic extent that suits that area best. Take a look at the projections that come built in with d3.geo and the projections extension.

So, let’s set up those key components.

Javascript

Canvas Dimensions

var width = 960;
var height = 500;

SVG

var svg = d3.select('body').append('svg')
    .attr('width', width)
    .attr('height', height);

Projection

var projection = d3.geo.albersUsa()
    .scale(1000)
    .translate([width / 2, height / 2]); 
    // https://github.com/mbostock/d3/wiki/Geo-Projections#wiki-translate

Path

var path = d3.geo.path()
    .projection(projection);

Data (Topojson)

d3.json('js/world.json', function(error, us) {
    svg.append('path')
        .datum(topojson.feature(us, us.objects.state))
        .attr('class', 'states') // defined in CSS
        .attr('d', path);
});

CSS

.states {
    fill: #e5e5e5;
    stroke: #fff;
    stroke-width: 2px;
}

Depending on the scale of your project, the javascript can sit within the body of your `index.html` file or it can be within a separate file if you have more functionality to build into the map.

View the working file on bl.ocks.org.</p>