Add an animated icon to the map
Add an animated icon to the map that was generated at runtime with the Canvas API. Requires Trimble Maps v3.0.0 or later.<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Add Image Animated</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.3.css" /> <script src="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.3.js"></script> <style> body { margin: 0; padding: 0; } html, body, #map { height: 100%; } </style> </head> <body> <div id="map"></div> <script> TrimbleMaps.setAPIKey('YOUR_API_KEY_HERE'); const map = new TrimbleMaps.Map({ container: 'map', zoom: 5, style: TrimbleMaps.Common.Style.TRANSPORTATION, }); const size = 200; // implementation of StyleImageInterface to draw a pulsing dot icon on the map // Search for StyleImageInterface in https://developer.trimblemaps.com/maps-sdk/api/ const pulsingDot = { width: size, height: size, data: new Uint8Array(size * size * 4), // get rendering context for the map canvas when layer is added to the map onAdd() { const canvas = document.createElement('canvas'); canvas.width = this.width; canvas.height = this.height; this.context = canvas.getContext('2d'); }, // called once before every frame where the icon will be used render() { 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 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 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('points', { type: 'geojson', data: { type: 'FeatureCollection', features: [ { type: 'Feature', geometry: { type: 'Point', coordinates: [0, 0], }, }, ], }, }); map.addLayer({ id: 'points', type: 'symbol', source: 'points', layout: { 'icon-image': 'pulsing-dot', }, }); }); </script> </body> </html>
Add an animated icon to the map
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Add Image Animated</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.3.css" /> <script src="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.3.js"></script> <style> body { margin: 0; padding: 0; } html, body, #map { height: 100%; } </style> </head> <body> <div id="map"></div> <script> TrimbleMaps.setAPIKey('YOUR_API_KEY_HERE'); const map = new TrimbleMaps.Map({ container: 'map', zoom: 5, style: TrimbleMaps.Common.Style.TRANSPORTATION, }); const size = 200; // implementation of StyleImageInterface to draw a pulsing dot icon on the map // Search for StyleImageInterface in https://developer.trimblemaps.com/maps-sdk/api/ const pulsingDot = { width: size, height: size, data: new Uint8Array(size * size * 4), // get rendering context for the map canvas when layer is added to the map onAdd() { const canvas = document.createElement('canvas'); canvas.width = this.width; canvas.height = this.height; this.context = canvas.getContext('2d'); }, // called once before every frame where the icon will be used render() { 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 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 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('points', { type: 'geojson', data: { type: 'FeatureCollection', features: [ { type: 'Feature', geometry: { type: 'Point', coordinates: [0, 0], }, }, ], }, }); map.addLayer({ id: 'points', type: 'symbol', source: 'points', layout: { 'icon-image': 'pulsing-dot', }, }); }); </script> </body> </html>