Combining D3 and Ember to Build Interactive Maps
An outline map of the States in the USA
We’ll get stated building an Ember app to draw a map of the USA with each state outlined.
First, we’ll need to know what each State looks like. This information is available to download from http://data.jquerygeo.com/usastates.json.
This is a GeoJSON format which Thomas Newton points out in his post Positioning and Scaling maps in D3 is a format that works really well with D3 since it is data that can be rendered into SVG by our code. Each State’s boundaries are defined in complete detail with polygons that a cartographer has drawn out for us. This works for rectangular States like Colorodo or Wyoming and amazingly also works for those with lots of coastline like Louisiana or Alaska (although the polygons are much more complicated).
Now, to create an Ember app we need to create our application and we’ll assign the GeoJSON data into a bindable property.
Next we’ll add some handlebars expressions to our html page telling it to display the map as an Ember View (we’ll create that in a minute).
Finally we write the view
Whew that is a bit of code so let’s dig in. This is where we use
d3 to create the svg that looks like a map of the USA.
d3 (Data-Driven Documents) works by binding data to your DOM then applying tranformations to that data.
In this case our data is the GeoJSON file and our tranformations turn it into an SVG map.
didInsertElement is called by Ember when the view is inserted into the page’s DOM.
- The first two lines use
d3.selectto add the
<svg><g id="regions">elements to the page on this view’s portion of the page.
- The remaining use
d3.selectAll.data.enterto loop through the features (each State) and add a
- Looping through each feature (ie. State), we make use of the rest of the code and set the
dattribute to the value of the
pathlogic scales the map and uses the
albersUsaprojection which moves Alaska and Hawaii to the bottom left where we usually see them on maps.
Looking at code is fun but what does it look like? Below is the page we just built and the you can see that it does, in fact, look like a map of the USA with each State outlined.
Coloring the States red or blue
A red/blue map isn’t much use when all the States are white so let’s color them in.
First we’ll need some data with the election results so we know what color each State should be. There’s a source from Google at http://code.google.com/p/general-election-2008-data/source/browse/trunk/json/votes/2008. I found the format to be a little hard to work with so I processed it into a simpler json file with just the information we’ll need. It looks like:
To use it we’ll save it in our Ember Application.
map function to turn our json data into ember objects that we can put into an Ember
For this example we don’t really need these ember objects but in a real application we’d probably get some requirements that would make them useful.
For instance if we wanted the colors to update on election night as new results come in.
Since we are using the
StateResults objects, we need to define them next.
Both objects are pretty simple. In fact they would both be empty except for the
findByName accessor we define on
We’ll see the need for that in a minute when we look at how the view decides whether to color a State red or blue.
This takes us to the view which enhances what we had before:
Most of the view is the same, all that’s different is the way we set the fill on each State (“feature” in d3 terms).
.attr('fill', this.updateFillFor);- Instead of setting the “fill” attribute to ‘white’ for all States we now provide a function to make the decision differently for each State. D3 will call the function with the current State as an argument (it actually passes the D3 “datum” object).
updateFillFor- This function uses the
findByNamefunction we defined in
StateResultsto match the “geographical” State with the “election result” State. They are separate because each came from a different external json source. Once we have the stateResult object we look at the winner and know to return either “red” or “blue”.
We can see it all working together right here and yes it does look like all the other red/blue election maps you’ve seen.
This is just the beginning of what you can do by combining D3.js with Ember.js. Next I plan to write about how you could add behavior like clicking to select a State and let Ember show details about that State.