D3: Topojson Interaction

bl.ock, gist

Interacting with the geographic data on your map is what gives web-maps a step up compared to static maps. All of that spatial information can hold it’s own attribute info, much like shapefiles. And all of that information is accessible on browser side with D3 and array interactions.

Simply, as the user interacts with the map, you can set which information should be returned to them. To take it one step further, you can use this information to computer new relationships and trends that effectively give web-mapping with spatial data a GIS feel. Upon updating your data, all of your spatial statistics will update as well, which doesn’t require you to re import your data as if you were creating a static map.

Taking from the previous example, how to render topojson data, the interaction portion is actually just a simple addition, but is only possible with the array created by D3. We’ll add the action item .on('mouseover', ...) to the data rendering process:

.on('mouseover', function(d) {
    // grab specific data
    // use specific data

The interactions with geographic data are numerous: 'mouseover', 'mouseout', 'mousedown', 'mouseup', 'mousemove'. The following example looks for the STATE_ABBR property, passes it to a specific element in the HTML, and changes the style of the SVG element on the cursor entering and exiting the element.

d3.json('us.json', function(error, us) {
        .data(topojson.feature(us, us.objects.usStates).features)
        .attr('class', 'states')
        .attr('d', path)
        .on('mouseover', function(d){
            // get state abbreviation
            var name = d.properties.STATE_ABBR;
            // add to element
            return document.getElementById('name').innerHTML=name; 

A key component to this process is the difference between .data() and .datum(). In the topojson rendering tutorial, I used .datum() to define the source of the geometry. Datum is the singular of data. Therefore, your data object is treated as a single SVG object. Using .data() treats each iteration of the data as its own SVG element, allowing you to interact with each separately. The code difference is minimal, but the effect is enormous. See what datum would do to your interactions with the svg canvas.