Animate a line
Animate a line by updating a GeoJSON source on each frame.
Mapbox GL unsupported
Mapbox GL requires WebGL support. Please check that you are using a supported browser and that WebGL is enabled.
<!DOCTYPE html><html><head><meta charset='utf-8' /><title>Animate a line</title><meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /><script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.0/mapbox-gl.js'></script><link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.0/mapbox-gl.css' rel='stylesheet' /><style>body { margin:0; padding:0; }#map { position:absolute; top:0; bottom:0; width:100%; }</style></head><body> <style>button {position: absolute;margin: 20px;} #pause::after {content: 'Pause';} #pause.pause::after {content: 'Play';}</style><div id='map'></div><button id='pause'></button><script>mapboxgl.accessToken = '<your access token here>';var map = new mapboxgl.Map({container: 'map',style: 'mapbox://styles/mapbox/streets-v10',center: [0, 0],zoom: 0.5}); // Create a GeoJSON source with an empty lineString.var geojson = {"type": "FeatureCollection","features": [{"type": "Feature","geometry": {"type": "LineString","coordinates": [[0, 0]]}}]}; var speedFactor = 30; // number of frames per longitude degreevar animation; // to store and cancel the animationvar startTime = 0;var progress = 0; // progress = timestamp - startTimevar resetTime = false; // indicator of whether time reset is needed for the animationvar pauseButton = document.getElementById('pause'); map.on('load', function() { // add the line which will be modified in the animationmap.addLayer({'id': 'line-animation','type': 'line','source': {'type': 'geojson','data': geojson},'layout': {'line-cap': 'round','line-join': 'round'},'paint': {'line-color': '#ed6498','line-width': 5,'line-opacity': .8}}); startTime = performance.now(); animateLine(); // click the button to pause or playpauseButton.addEventListener('click', function() {pauseButton.classList.toggle('pause');if (pauseButton.classList.contains('pause')) {cancelAnimationFrame(animation);} else {resetTime = true;animateLine();}}); // reset startTime and progress once the tab loses or gains focus// requestAnimationFrame also pauses on hidden tabs by defaultdocument.addEventListener('visibilitychange', function() {resetTime = true;}); // animated in a circle as a sine wave along the map.function animateLine(timestamp) {if (resetTime) {// resume previous progressstartTime = performance.now() - progress;resetTime = false;} else {progress = timestamp - startTime;} // restart if it finishes a loopif (progress > speedFactor * 360) {startTime = timestamp;geojson.features[0].geometry.coordinates = [];} else {var x = progress / speedFactor;// draw a sine wave with some math.var y = Math.sin(x * Math.PI / 90) * 40;// append new coordinates to the lineStringgeojson.features[0].geometry.coordinates.push([x, y]);// then update the mapmap.getSource('line-animation').setData(geojson);}// Request the next frame of the animation.animation = requestAnimationFrame(animateLine);}});</script> </body></html>