#30DayMapChallenge Day 3. Polygons
City Tiles 🏙️
This is a OSM buildings vector tiles map made using D3.js and Nextzen, that I have prepared for #30DayMapChallenge on Twitter in 2021. You can find out more about the challenge and my other maps in this post.
You can watch a short movie that shows the functionality on YouTube.
Goal: A map with polygons.
Live: https://maptheclouds.com/playground/30-day-map-challenge/polygons/
Tweet: https://twitter.com/maptheclouds/status/1455980347066302471
Code: https://github.com/alexaac/map-challenges/tree/master/polygons
Description:
The visualization shows the Timișoara historical center, România.
Data: OSM Buildings, Nextzen
Tags: #D3js #Nextzen #OSMBuildings #VectorTiles
Inspiration:
https://osmbuildings.org/documentation/data/
https://www.nextzen.org/
OSM buildings vector tiles with D3.js and Nextzen – making of
Challenges: For this map, I want to test vector tiles loading from different sources. Therefore, I use several layers to draw background from Nextzen, and add a buildings layer above from OSM Buildings. In order to obtain the data, I connect to specific data API’s and receive it tile by tile, using d3.tile.
First, I load the data for the layers in the background: background, water, earth and roads layers. Then I load the layer for the background, the buildings. After that, I use D3.js to style and display them, too.
const buildings = g
.selectAll('g.buildings')
.data(tiles.features)
.enter()
.append('path')
.style('fill', '#3288bd')
.style('fill-opacity', 1)
.attr('d', path)
.style('stroke-width', 0.1)
.style('stroke', '#000');
However, loading tiles from different sources proves to be a tricky process. The biggest challenge with this map was to load all tiles from the Nextzen API before loading the buildings. Otherwise, some building tiles would have been covered by earth tiles.
In order to solve this issue, first I have used Promise.all and async to get base data with d3.tile.Then I have loaded the buildings only after all background layers were already on the page. Moreover, all the tiles from the Nextzen API had to be loaded before styling them, to prevent the same overlapping issue.
return Promise.all(promises)
.then((data) => {
// Wait for the Nextzen tiles to complete, then render the OSM tiles
renderBuildings();
return data;
})
.catch((error) => console.log(error));
};
TODO: add seamless zoom, create print layout
To conclude, I must say I have enjoyed making this map and I have learned more about using vector tiles data from API’s to make maps in D3.js.