Countries and Capitals with D3 and Natural Earth
Countries and Capitals D3 Demo
Can you recognize the country and capital in the picture above? If you have been playing around with Natural Earth vector and raster map data, which is a great free geographical resource, chances are this large area of the earth will not be clearly defined. To be fair, the name of this self-declared de facto sovereign state is included in Natural Earth data, but when we convert the shapefiles to GeoJSON or TopoJSON, that name is rarely included. It could be included, but it makes sense to leverage some standards when doing a mapping between names and areas, and the unrecognized state of this country results in no corresponding ISO code. As a result, most D3.js geo examples will have this area undefined or will show a -99 identification.
Considering the size of this land, I think that we might need a new standard on how we do mappings. There are actually 16 places in the Natural Earth Database that are missing ISO 3166 codes. Most of them are tiny, or unknown, but Somaliland and a place like Kosovo should have some code. There are also some inconsistencies the other way, like these 4 lands that do have ISO 3166 codes but are missing from Natural Earth:
You could argue that places like Svalbard and Jan Mayen are just Norway but I would expect Vatican City to be represented. Perhaps it is too small even at 10m scale. If we consider capitals, we also have some issues. First of all, where do you find accurate list of capitals for all countries or territories with geographical information? My first guess was World Bank, but while their API service cleanly returned 256 capitals in XML format, Anguilla wasn’t there. I know that Anguilla is a British overseas territory but Wikipedia shows that The Valley is the capital of Anguilla and I think that is what most people would expect to see on a map. I have also tried the CIA World FactBook listing of capitals, but it also has missing data. For example, Åland Islands and the capital of Mariehamn is not included.
In terms of capitals, there are many places, even the massive Antarctica, without any capital city. Other places like Israel and the State of Palestine both claim the same capital: Jerusalem. And then we have places like Tokelau where the capital rotates yearly. So, a direct 1-1 mapping of each country/territory to a capital city is not possible, but I wanted to get really close and present this data in JSON format. Using WikiPedia, World Bank, and the CIA Factbook I was able to put together a decent list of countries and capitals with latitude and longitude data. For the zoomed out world map, I used the already created world-110m TopoJSON file but changed the the ids of Somaliland, Kosovo, and Northern Cyprus to XX1, XX2, and XX3. This is because all other territories have used the 3 letter ISO code and for now, I have decided to keep leveraging that standard.
Since this demo is about exploring countries or lands up close, I wanted to retrieve more accurate land data. Mike Bostock’s TopoJSON repository on GitHub has the world in 110m and 50m scales but I could not find anything in 10m scale. I also wanted to leverage all the additional data that is provided by Natural Earth for each territory (economy, income group, population, etc). I download the 10m shapefile from Natural Earth and converted it to TopoJSON while storing the interesting country details in a separate CSV file. I made 2 TopoJSON files, one only grabs the spatial data with standard TopoJSON settings (world-10m.json) and the second one captures more details at that scale and uses the ISO 3 letter code for identification (world-NE-10m.json).
At this scale and level of detail, the TopoJSON file expands to 3.7 megabytes (still so much smaller than 21.4MB GeoJSON file). Since I don’t need to load all this detail at a world level (for that I can use 110m scale), I decided to split this one file into individual TopoJSON files for each country. So, initially, I load the CSV file used for country data and mappings and I load the world at 110m scale as a nice zoomed out world map. I am leveraging my World Map geo boilerplate to make sure the map is rendered according to screen size with nice tooltips and scale/zoom calculation.
You can click on any country using a mouse or use the select box and that retrieves the individual country TopoJSON file, renders the spacial data with a proper zoom and scale, and plots down the capital using the capitals.json file. I show the details captured from Natural Earth (ISO codes, population, etc) in a table below the map. On the world map level, you can select certain income groups or economies to highlight the countries in these categories. Finally, I provided an “Export to Image” button that converts any D3 map into an SVG image.
Check it out, here is the final demo.
Here is the code and all the files in a compressed zip.
Countries by Area
Geo Coords Converter
ISO 3166 3 Letter Codes
Natural Earth 10m Raster Data