Initializing the map does more than just create a container in the map
div: it also tells the browser to request the Mapbox Studio style. This can take variable amounts of time depending on how quickly the Mapbox server can respond to that request, and everything else you're going to add in the code relies on that style being loaded onto the map. As such, it's important to make sure the style is loaded before any more code is executed.
Fortunately, the map object can tell your browser about certain events that occur when the map's state changes. One of these events is load
, which is emitted when the style has been loaded onto the map. Through the map.on
method (you will use this in the next stage), you can make sure that none of the rest of your code is executed until that event occurs by placing it in a callback function that is called when the load
event occurs. More info at Mapbox help.
After the map has been initialised (closed brackets) add the following.
Update the URL and source-layer shown in bold with the relevant ones in your mapbox account.
Here we are adding a layer to our map from our source. The type is 'fill-extrusion' meaning it is an extruded (3D) polygon. The paint section indicates the size of the height of the polygon - which using the building height column 'bldhgt_ahd'
map.on('load', function() {
map.addLayer({
'id': 'newBuildings',
'source': {
'type': 'vector',
'url': 'mapbox://ENTER THE MAPBOX TILESET MAP ID'
},
'source-layer': 'ENTER THE MAPBOX TILESET TITLE',
'type': 'fill-extrusion',
'paint': {
'fill-extrusion-height': {
'type': 'identity',
'property': 'bldhgt_ahd'
},
}
});
});
The building data loads on the map and is filled in black (default fill colour):
One way to colour the buildings by the status of the building is to add an array of status names and colours and then a for loop to loop through them.
Add two new variable arrays after map.on('load', function() {
var statusNames = ['APPLIED', 'APPROVED', 'UNDER CONSTRUCTION', 'COMPLETED'];
var statusColors = ['#08519c', '#6baed6', '#c6dbef', '#999999'];
These colours are chosen specifically from colorbrewer a great source for choosing colours for your maps.
Prior to the map.addLayer({
add a for loop so that each of the buildings are coloured by their status:
for (var i = 0; i < statusNames.length; i++) {
We then create some variables for the single colour in an our array:
var statusName = statusNames[i];
var statusColor = statusColors[i];
Then follow these steps to make sure the loop is accessing the right data:
statusName
'fill-extrusion-color': statusColor,
'filter': ['==', 'status', statusName]
Finally, so we can see through our buildings slightly add an opacity filter: within paint also add: 'fill-extrusion-opacity': 0.7
The final code for the full map.on
function you have should now look similar to this (the bold will be your access id and tileset id):
map.on('load', function() {
var statusNames = ['APPLIED', 'APPROVED', 'UNDER CONSTRUCTION', 'COMPLETED'];
var statusColors = ['#08519c', '#6baed6', '#c6dbef', '#999999'];
// Colour layers by their status and add an interactive legend
for (var i = 0; i < statusNames.length; i++) {
var statusName = statusNames[i];
var statusColor = statusColors[i];
map.addLayer({
'id': statusName,
'source': {
'type': 'vector',
'url': 'mapbox://ENTER THE MAPBOX TILESET MAP ID'
},
'source-layer': 'ENTER THE MAPBOX TILESET TITLE',
'type': 'fill-extrusion',
'paint': {
'fill-extrusion-color': statusColor,
'fill-extrusion-height': {
'type': 'identity',
'property': 'bldhgt_ahd'
},
'fill-extrusion-opacity': 0.7
},
'filter': ['==', 'status', statusName]
});
};
});