Add a Nextzen cities text layer
This example adds a city text layer to a map using the Nextzen vector tile service (opens in a new tab) and filtered to only include features whose type
property is equal to locality
.
The text layer displays city names at various zoom levels and adjusts the font size based on the population of the city.
nextzen-cities.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>MapsGL SDK - Add a Nextzen cities text layer</title>
<meta name="description" content="Add city text labels from a Nextzen vector tile source scaled by population." />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="https://api.mapbox.com/mapbox-gl-js/v2.8.0/mapbox-gl.css" rel="stylesheet" />
<script defer src="https://api.mapbox.com/mapbox-gl-js/v2.8.0/mapbox-gl.js"></script>
<link href="https://cdn.aerisapi.com/sdk/js/mapsgl/latest/aerisweather.mapsgl.css" rel="stylesheet" />
<script defer src="https://cdn.aerisapi.com/sdk/js/mapsgl/latest/aerisweather.mapsgl.js"></script>
<style>
body, html {
margin: 0;
padding: 0;
}
#map {
height: 100vh;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
window.addEventListener('load', () => {
mapboxgl.accessToken = 'MAPBOX_TOKEN';
const map = new mapboxgl.Map({
container: document.getElementById('map'),
style: 'mapbox://styles/mapbox/light-v9',
center: [-93, 40],
zoom: 4
});
const account = new aerisweather.mapsgl.Account('CLIENT_ID', 'CLIENT_SECRET');
const controller = new aerisweather.mapsgl.MapboxMapController(map, { account });
controller.on('load', () => {
// Hide Mapbox labels
const map = controller.map;
map.style.stylesheet.layers.forEach(function(layer) {
if (layer.type === 'symbol') {
map.setLayoutProperty(layer.id, 'visibility', 'none');
}
});
const source = controller.addSource('nextzen', {
type: 'vector',
url: 'https://tile.nextzen.org/tilezen/vector/v1/256/all/{z}/{x}/{y}.mvt?api_key={nextzen_key}'
});
const layer = controller.addLayer('nextzen-cities', {
type: 'text',
source: 'nextzen',
sourceType: 'point',
sourceLayer: 'places',
filter: ['all', ['==', 'kind', 'locality']],
paint: {
text: {
value: {
property: ['name:en', 'name']
},
weight: (data) => {
if (data.kind === 'region') {
return 'bold';
}
return 'normal';
},
size: (data) => {
const z = data.zoom;
if (data.kind === 'country') {
if (z < 4) {
return 13;
}
return 20;
} else if (data.kind === 'region') {
if (z < 4) {
return 10;
}
return 12;
}
const mapValue = (number, [inMin, inMax], [outMin, outMax]) => {
number = Math.max(inMin, Math.min(inMax, number));
// if you need an integer value use Math.floor or Math.ceil here
return (number - inMin) / (inMax - inMin) * (outMax - outMin) + outMin;
};
if (z < 4) {
return 12;
}
return mapValue(data.population, [0, 5_000_000], [12, 20]);
},
transform: (data) => {
if (data.kind === 'region') {
return 'uppercase';
}
return 'none';
},
letterSpacing: (data) => {
if (data.kind === 'region') {
return 0.1;
}
return 0;
},
color: (data) => {
if (data.kind === 'region') {
return '#999';
}
return '#555';
},
outlineColor: '#fff',
offset: { x: 0, y: 0 }
},
symbol: {
pitchWithMap: false,
rotateWithMap: false
}
}
});
});
});
</script>
</body>
</html>