In the process of building Odyssey, I came across an omission in most of the world structures on Bl.ocks. Pretty much everyone nowadays grabs the Natural Earth
ne_110m_admin_0_countries dataset, converts it to TopoJSON, throws the result to a projection such as
and then move on with their lives.
But what if you care about information on this projection? What if Mike Bostock’s World Tour gave you this grandiose idea of an interactive globe for your website that needs to pinpoint tiny countries like Singapore?
Singapore and other small countries like it are not included in the main 1:110m scale data as they are not large enough to be polytopes. Instead, they are relegated to
ne_110m_admin_0_tiny_countries as point information and usually omitted from D3 1:110m globe implementations.
Including this data set adds a small amount of complexity to the build and a bit of finessing of the finished product, but nothing over the top. I’ll assume you have TopoJSON setup already and know how to use it. If not, checkout Let’s Make A Map for a good overview. For the lazy ones you can grab the end result of the following steps from here.
Get the latest data from Natural Earth. This can be whatever you want to combine; I’ll be using just countries and tiny country points, but it’d also be possible to use the sovereignty data in place of countries (for example) if you want to drill down a little deeper. Using the 1:50m or 1:10m sets is also fine, however I find that this is too precise (read: too much info) to animate smoothly on your grandma’s computer or mobile devices.
Extract both sets into a new directory and convert the shape data to GeoJSON:
We now need to manually merge these files. AFAIK,
ogr2ogr isn’t happy merging poly and non-poly geometry, and the
TopoJSON command line tool doesn’t merge stuff at all. It’s possible to merge this data on the client side each load, but this seems pretty inefficient. One could write a simple shell script for this, but as we’re only doing it once I see no need for automation. The GeoJSON format we have output with our two files above follows a simple syntax:
with a plethora of
Feature elements filling the array. To merge the data one must simply add a comma (
,) to the last entry of the
features array, then append the contents of the same array from
tinycountries.json. For this example we’ll save that file as
Now, our newly created file can be converted to TopoJSON via
and loaded using a somewhat normal D3 map routine. The important part is the
d3.json function. Here we don’t use a mesh load but rather a path append:
So what’s going on with all of those dots everywhere? Well; they’re our small countries, which are not represented by paths but rather just points. On this map they stick out like a sore thumb and it’s for this reason they are separated out in the first place. We don’t really want to see them either: just be able to reference them and zoom to their location.
To do this one can modify the
.data(land) item to include a filter
su_a3id or name and in-turn, center the viewport on a country even if it isn’t visible on this scale. The map below is filtering out ONLY tiny countries and giving you a world tour. Full codebase for this globe is here.
For a better demo of what can be done with this, checkout my photoblog Odyssey.