Animate a line
Animate a line by updating a GeoJSON source on each frame.
<!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://cdn.jsdelivr.net/npm/@goongmaps/goong-js@1.0.9/dist/goong-js.js"></script><link href="https://cdn.jsdelivr.net/npm/@goongmaps/goong-js@1.0.9/dist/goong-js.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>goongjs.accessToken = '8qzxZAuxcsctSlmOszInchP1A5GrmRBHJwCBCjO6';var map = new goongjs.Map({container: 'map',style: 'https://tiles.goong.io/assets/goong_map_web.json',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 () {map.addSource('line', {'type': 'geojson','data': geojson}); // add the line which will be modified in the animationmap.addLayer({'id': 'line-animation','type': 'line','source': 'line','layout': {'line-cap': 'round','line-join': 'round'},'paint': {'line-color': '#ed6498','line-width': 5,'line-opacity': 0.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').setData(geojson);}// Request the next frame of the animation.animation = requestAnimationFrame(animateLine);}});</script> </body></html>