In previous parts of this article, we described how to get geographical and manipulate them for our needs.
D3 is a library usable in a Web page to visualize data as charts or maps. Whereas the library provides a low-level API, it provides facilities to build them in a few lines of code. It also provides a support to use TopoJSON data to convert them in something that can be displayed with SVG or HTML5 canvas.
The first thing to do is to include the D3 and TopoJSON library in the HTML page that will contain the map. This can be simply done basing on the d3.org website, as described below:
We will display TopoJSON contents basing on the SVG support of browsers and D3. Let’s start by creating an svg element.
As you can see, the map is structured with “layers” using some g SVG elements.
In the context of maps, we need to specify a projection according to what we want to display. For France, the Lambert conformal conic projection, or simplier, the Lambert projection, is commonly used. It can be configured using the d3.geo.conicConformal function.
The projection object allows us to specify the map center and its scale. The “path” variable configured with the project will be used to build all the elements of the map with SVG. It will be used later.
Displaying outlines of towns
Now we have all the foundations of our map, let’s display the outlines of towns of Seine-et-Marne. We will start from a file containing all the outlines of towns in the Paris area. We need to restrict only those located in the department. Tools “ogr2ogr” and “topojson” will be very helpful here.
Don’t forget the -p parameter to include properties in the generated TopoJSON file.
We have now only the data we need. Let’s display them using D3. One of its strengths consists of adding elements and applying properties on a set of elements leveraging method call chaining. D3 provides for this a selection mechanism based on the selectAll, data and enter methods.
In the following snippet, we add a path element for each data of our TopoJSON file.
It’s a good start for sure but we can do better !Let’s add a bold outline around the department. For such use case, TopoJSON provide the topojson.mesh function. The latter is helpful to identify edges of outlines. It accepts a function as parameter for this. If we are in the case of an edge, its two parameters are equals. We can select it by returning true. For these elements, we can override border properties to make them thicker.
Add also a shadow and borders of departments of Ile-de-France in a similar way but without town ones. We don’t polluate this article with suc code but you can find it in the source code.
Here is the result !
In the context of SVG, here are the styles used:
- fill: background color of an area
- stroke: border color of an area
- stroke-width: width of the outline of an area
- opacity: transparency level
Apply now on this map the hints regarding inhabitants.
Visualizing inhabitants per town
The first thing to do is to choose the color palette that we want to use. Color Brewer (http://colorbrewer2.org/) provides such palettes for a use in maps. We choose here the “YlOrBr” palette with orange shades.
We now deduce corresponding intervals directly from data. The more the number is high, the more the color will be dark.
Data regarding population of towns are stored within a CSV file that we need to load using an AJAX request the way we did for their shapes. As we have now several requests, we need to wait for the loading of all data before proceeding them. D3 provides a support for this through its “queue” module (https://github.com/mbostock/queue). When all data were received, a callback function is called with corresponding data as parameters.
We didn’t define previously any color in the fill attribute (none value) of path elements for shapes of towns. One of the D3 strength consists of using a value but also a function that deduces this value from the current element. This last approach corresponds to our need since the color will now depend on the population of the town.
Let’s now have a look at the result. The background color of a town depends now of its population.
Adding a title and a legend
In order to make our map more readable, we can add a title and a legend for the used colors. This simply correspond to add rectangles and text areas with the SVG support of D3.
The following snippet describes how to build the title area.
A similar code can be implemented for the legend based on the different scale values of the number of inhabitants.
We display these two areas on the left of the map of Seine-et-Marne to make it look better.
To enhance our map a bit more, we can also add localisations and names of main towns. These towns will be positionned using their coordinates found on the Internet. From these latters, we build a CSV file with the following structure:
- town: the name of the town
- lat: the latitude of the town
- lon: the longitude of the town
Displaying these towns can be done in two steps: positionning a point and adding a text area to display its name.
Add circles for each town location, as described below:
Rectangles and text areas are added in the same way than for title and legend. We don’t show again.
D3 allows you to add dynamics to our map to display hints regarding a town by simply by hovering the mouse on the corresponding area. For this we need to register handlers for “mouseover” and “mouseout” events. In the first case, we display the tooltip, position it right besides the mouse cursor and display the right hints in it. In the second case, we hide it.
The following snippet describes how to implement this processing.
The tooltip is now dynamically displayed according to the mouse position on the map.
Displaying additionnal data
It’s also possible to still extend the map by adding for example rivers from OpenStreetMap. For this, we can simply apply the TopoJSON content of the “waterways” as previously done for town shapes:
Here is the final result of our map!