Saturday, May 17, 2014

Around the world in eighty days

This post is content previously published on www.cathmhaol.com

One of the projects I've been working on is developing a map that will visually represent data. This seems easy enough, but when practice meets theory, it hasn't been.

My project is fairly straightforward. Take a collection of quantifiable global information - it could be nearly any quantifiable information - e.g., the amount of money moving in or out of world banks, kilowatt hours consumed, number of mobile users, or the number of take-off and landing events at world airports - and tie it to a location like a city. Then represent the relative activity with a marker on a map. So basically, translating data that we might find in a table into a visual format.


CountryCityActivity
USATL68343
USORD59692
USDFW56496
USLAX51396
CNPEK48226
USCLT44583
USDEN44438
USLAS41164
USIAH39808
GBLHR37680


Beyond the basic requirement - to visually represent the data - there were a few other requirements I had set for myself. I didn't want the map to just be a two-dimensional projection - like a Mercator - I wanted it be a globe that rotates.

One option was a WebGL map - something like Akamai's GNET globe - but that doesn't work in Safari, practically eliminating iOS devices. Another option was planetary.js - which works most everywhere but didn't have the functionality I needed, mainly because it uses an HTML canvas instead of an SVG. I was left to build what I needed.

Even though the planetary.js library was slightly inadequate, it gave clues that led me to the library published as D3.js - which made building the exact tool I needed easy. Additionally, there are several online examples and tutorials that explain how to use D3 and topoJSON to create maps, making it a simple matter to generate the map. Add in the ability to zoom, for which there are hooks in the D3 library and a little finesse in JavaScript to convince the library that touch events should be handled like mouse events, and I had a nearly fully-functional globe with countries in a short amount of time.

Next came the markers...

First, we need some way of identifying the latitude and longitude of cities...or in our example data, airports. To accomplish this, I built a massive JSON file that contains nearly every airport, the country it is in, and the coordinates (which is airports.json in one of my GitHub repos, along with coordinates of most major cities). With this, it's a simple matter of mapping an airport to a specific point on the grid.

Once I had the coordinates, I needed some way to represent the relative size...which is really just a matter of creating a scale based on the smallest and largest numbers in the dataset. Here's where it gets a little tricky...because we want the markers to do something - be animated in some way. Transitions and animations are pretty time consuming, but luckily D3 again fills the gap. By using two somewhat clever transitions and fiddling with the timing, there are two slightly different animations - pulse and ping - that give the markers extra visual appeal.

Of course, the visual appeal of the rotating globe doesn't really solve all the problems, even with the ability to stop the globe and drag it to turn it or even zoom in or out. People see the animated markers and can see that traffic is heavier in ATL than in LHR, but the actual data is now hidden. To expose the data, I added a scrollable, sortable table to the library.

By specifying the columns or properties of the data elements that you want to display, a table is generated and attached to the same DOM node that contains the SVG with the map. By again using D3, we quickly make the table sortable - meaning users can click on the headers to sort by that property, e.g., clicking on the Country header to sort by country. Since there is likely little real estate available when a globe is present, I limit the table to around 10 rows and make it scrollable - the CSS to accomplish this is generated by the library and appended to the DOM when the table is generated.

You can find prototypes for both the marked map and the scrollable table at products.cathmhaol.com. You can find the D3 plugin that will do all this in my GitHub D3 plugins repo. Feel free to fork the repo, or if you'd rather, let me know what you'd like to see changed - maybe your requests will make it into the official repo.

No comments:

Post a Comment