All docsNMaps GL JS DocsExamplesGenerate and add a missing icon to the map

Generate and add a missing icon to the map

This example uses addLayer to add a layer to a style, but it references an image that does not exist in the style's sprite or list of available images. Since the image is missing, the property that references the image throws a styleimagemissing event.

This example uses that styleimagemissing event to detect the missing image, then it generates a new image and adds that image to the map style with addImage within the event listener callback to make sure that an icon is rendered even if the referenced image is missing.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Generate and add a missing icon to the map</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://cdn.ndrive.com/nmapsgl/v1.6.6/nmaps-gl.js"></script>
<link href="https://cdn.ndrive.com/nmapsgl/v1.6.6/nmaps-gl.css" rel="stylesheet" />
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
// TO MAKE THE MAP APPEAR YOU MUST ADD YOUR ACCESS TOKEN
nmapsgl.accessToken = '<your access token here>';
const map = new nmapsgl.Map({
container: 'map',
style: 'Streets'
});
map.on('styleimagemissing', (e) => {
const id = e.id; // id of the missing image
// check if this missing icon is one this function can generate
const prefix = 'square-rgb-';
if (id.indexOf(prefix) !== 0) return;
// extract the color from the id
const rgb = id.replace(prefix, '').split(',').map(Number);
const width = 64; // The image will be 64 pixels square
const bytesPerPixel = 4; // Each pixel is represented by 4 bytes: red, green, blue, and alpha.
const data = new Uint8Array(width * width * bytesPerPixel);
for (let x = 0; x < width; x++) {
for (let y = 0; y < width; y++) {
const offset = (y * width + x) * bytesPerPixel;
data[offset + 0] = rgb[0]; // red
data[offset + 1] = rgb[1]; // green
data[offset + 2] = rgb[2]; // blue
data[offset + 3] = 255; // alpha
}
}
map.addImage(id, { width: width, height: width, data: data });
});
map.on('load', () => {
map.addSource('points', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [0, 0]
},
'properties': {
'color': '255,0,0'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [50, 0]
},
'properties': {
'color': '255,209,28'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-50, 0]
},
'properties': {
'color': '242,127,32'
}
}
]
}
});
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'points',
'layout': {
'icon-image': ['concat', 'square-rgb-', ['get', 'color']]
}
});
});
</script>
</body>
</html>