D3 World Maps: Tooltips, Zooming, and Queue
Update: I highly recommend checking out this responsive D3.js framework with pan and zoom limits and the new D3 World Map Template.
D3 has a lot of built in support (a powerful geographic projection system) for creating Maps from GeoJSON. If you have never used D3 for maps, I think you should take a look at this D3 Map Tutorial. It covers the essentials of making a map with D3 and TopoJSON, which I will use below in more advanced examples. TopoJson encodes topology and eliminates redundancy, resulting in a much smaller file and the GeoJSON to TopoJSON converter is built with NodeJS.
Thus, I encourage you all to start using TopoJSON and below, I will go over a couple examples of building a D3 World Map with colors, tooltips, different zooming options, plotting points from geo coordinates, and listening to click events to load new maps. I will also use Mike Bostock’s queue script to load the data asynchronously.
D3 World Map with Country Tooltips and Colors
Let’s start with something basic. We want a world map in TopoJSON so I have selected the world-110m.json from the TopoJSON examples folder. We also need a data file for world country names and you can find a TSV version here. Coloring in the map was pretty simple, I have used the D3 categorial colors function and a style attribute. If you want to make sure that no adjecent countries have the same color you can use the function in this World Map Color Example. I selected the mercator projection and used the queue asynchronous library mentioned above to load all the data. At the end of my ready function, I attached a mousemove and mouseout events to every country which populate and show the tooltip with the correct country name inside. Take a look at the example to see how it all works with queue, colors, and tooltips.
D3 World Map with Smooth Mouse Zooming
So, that was easy but now I want to add zooming functionality. It is also pretty straightforward as D3 has zoom behavior and on zoom you can call a redraw function which will zoom into the map. Take a look at the demo and notice how I only added a couple of lines around 64-71 which is all that is needed for zoom functionality. You can use your mouse wheel or doubleclick on any area in the map. I changed the thickness of the borders to .1 stroke-width because that looks better when you zoom in and I also realized that once you zoom in a lot, there is a lack of detail with the world-110.json map. I threw in the world-50m.json map and it looked much better but there were 5 problematic areas above Alaska which would not match on any country name. I am guessing that this is just bad data in the world-50m.json map as I cannot even locate any land or islands above Alaska in Google Maps. So, I added a hack: just a conditional that skips over 5 points where country name is undefined.
D3 World Map that Zooms to each Country on Click
You might have seen some examples of zooming into a country so I also wanted to show an example of how to build a world map where you can click on a country and it zooms into the right area. Mike Bostock’s provided a good answer on StackOverflow which explains how to center a map to a geoJSON object and this zoom to bounding box example is a great starting point. Instead of using the map of US, I have added the changes to my world map example and it now zooms on mouse click into each country. Check out the demo. The changes are really just two extra functions for handling the mouse clicks, extra CSS, plus drawing an extra “rect” element to reset or zoom out.
After making this demo I realized that it doesn’t really work well for big countries like Russia or countries like US where Alaska and Hawaii are specially separated from the mainland. You could, however, create an event listener on the zoom and load a new country map once the user has zoomed in for further detail (something like the map here). I have started working on this and have created a demo that works with clicking into United States and clicking out. In order to finish it, you would need to generate all the appropriate topoJSON maps for each country.
D3 World Map with Zoom, ToolTips, and Data Points
Going back to the regular zoom behavior, I wanted to finally show how you would add geo locations or data points to the map. Since we are working with a world map it makes sense to throw in the country capitals according to their latitude and longitude values. For the purpose of the demo, however, I have selected 3 random cities in the world and put them into a JSON object. It is important to note that longitude goes first when you define the geo coordinates for D3. Plotting them on the world map is also pretty simple, you just loop through that JSON object and transform the geo coordinates according to the projection you are using. Check out the demo and look at lines 133-140 to see how I did it. This example was quite helpful in plotting latitude and longitude points on a mercator projection.
I’m hoping this is helpful to someone trying to build maps with D3.
External:
Natural Earth Tables
Natural Earth Data in Google Maps
Natural Earth vectors in the cloud
Clean Up for Natural Earth GeoJSON
Airport, airline and route data
Flows of refugees between countries
Colors in D3.js
Human Footprints Map
Migrations Map
Chrome Browser Percentage Map with Raphael
World Borders Dataset
Expanded Gallery of ArcGIS Online Map Data
D3.js Geo fun
Map Projection Transitions
More GEO Mapping examples with D3
Japan GeoJSON in D3 with mouseover
Hierarchical Timeline Data with D3 and EmberJS