Add an animated icon to the map
This example creates an animated pulsing dot icon and adds it to the map.
It generates the 'pulsingDot' image at runtime with the Canvas API and uses the StyleImageInterface
specification to help render the animation on every frame.
When the map loads, it uses addImage
to add 'pulsingDot' to the style as an icon-image called 'pulsing-dot', then it uses addSource
to add a source called 'dot-point' with a single point feature at the coordinate location [0, 0]. Lastly, it uses addLayer
to create a symbol layer called 'layer-with-pulsing-dot' that uses the 'pulsing-dot' icon to represent the 'dot-point' feature on the map.
<!DOCTYPE html><html><head><meta charset="utf-8" /><title>Add an animated 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/v.1.6.8/nmaps-gl.js"></script><link href="https://cdn.ndrive.com/nmapsgl/v.1.6.8/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'}); const size = 200; // This implements `StyleImageInterface`// to draw a pulsing dot icon on the map.const pulsingDot = {width: size,height: size,data: new Uint8Array(size * size * 4), // When the layer is added to the map,// get the rendering context for the map canvas.onAdd: function () {const canvas = document.createElement('canvas');canvas.width = this.width;canvas.height = this.height;this.context = canvas.getContext('2d');}, // Call once before every frame where the icon will be used.render: function () {const duration = 1000;const t = (performance.now() % duration) / duration; const radius = (size / 2) * 0.3;const outerRadius = (size / 2) * 0.7 * t + radius;const context = this.context; // Draw the outer circle.context.clearRect(0, 0, this.width, this.height);context.beginPath();context.arc(this.width / 2,this.height / 2,outerRadius,0,Math.PI * 2);context.fillStyle = `rgba(255, 200, 200, ${1 - t})`;context.fill(); // Draw the inner circle.context.beginPath();context.arc(this.width / 2,this.height / 2,radius,0,Math.PI * 2);context.fillStyle = 'rgba(255, 100, 100, 1)';context.strokeStyle = 'white';context.lineWidth = 2 + 4 * (1 - t);context.fill();context.stroke(); // Update this image's data with data from the canvas.this.data = context.getImageData(0,0,this.width,this.height).data; // Continuously repaint the map, resulting// in the smooth animation of the dot.map.triggerRepaint(); // Return `true` to let the map know that the image was updated.return true;}}; map.on('load', () => {map.addImage('pulsing-dot', pulsingDot, { pixelRatio: 2 }); map.addSource('dot-point', {'type': 'geojson','data': {'type': 'FeatureCollection','features': [{'type': 'Feature','geometry': {'type': 'Point','coordinates': [0, 0] // icon position [lng, lat]}}]}});map.addLayer({'id': 'layer-with-pulsing-dot','type': 'symbol','source': 'dot-point','layout': {'icon-image': 'pulsing-dot'}});});</script> </body></html>