D3 Maps with Image Tiles
After creating some D3 maps, I wanted to investigate how to make these maps look better. I could definitely improve the presentation of the map element, use better colors for different countries, and make other minor changes but leveraging image tiles with D3.js would be cool. However, using an external tile server, loading a lot more resources, and paying performance costs are important considerations. So, today, I am going to explore different options for integrating map tiles with D3 and GeoJSON.
Looking around, there are a few examples of mixing MapBox tiles with D3 as well as OpenStreetMap Vector Tiles with D3, but these examples do not integrate any GeoJSON. Instead, they just load the tiles using D3 functions and use D3 projection functions to understand geographic locations. I have created a D3 example with MapBox and a D3 example with Natural Earth Vector Tiles and if you look at the rendered DOM you will not see any SVG elements but a map container with images.
This isn’t exactly my intention but it does illustrate how to use only D3 to create a map with image tiles. I want load the countries GeoJSON code to draw a map in D3 and then append image tiles to create a prettier map. For example, as the post image shows, I might want to only clip image tiles to land and keep the oceans blank. To do this, I load the TopoJSON world file (smaller than GeoJSON version) and then append image tiles to the rendered SVG. I leverage clip-path to only attach image tiles on land and as a result, I have a D3 World Map built with JSON and Image Tiles clipped to land.
I am loading the image tiles from MapBox Natural Earth map and I limited the zooming functionality to not request and redraw more tiles on zoom events. This does not load a ton of extra resources but it still grabs then from an external source (MapBox). Since I am dealing with a limited set of map tile images, nothing stops me from loading them locally by just changing the dynamic image location. Here is an example of a D3 World Map with local image tiles.
Now that we have done this clipping for a world map, what about other shapes? It could be geography based or something completely different. Lets consider fonts and letters, or a word with a map tile images in the background. I opened up Inkscape and created the word Boston and exported it as a combined SVG. I considered transforming the SVG into GeoJSON but that is really not necessary as the end result of D3 is SVG and I could just append the SVG paths. Here is an example of a word with map image tiles clipped to the font.
Responsive TopoJSON Sizing with d3.js
Gray Earth raster data reprojected to the U.S. National Atlas projection