Animate a line
Animate a line by updating a GeoJSON source on each frame.
Note
If you want to test this example, edit it in JSFiddle or CodePen and replace the "YOUR-OWN-API-KEY" and "YOUR-OWN-VPM-ID" placeholders with your actual api key and vpm id.<!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://unpkg.com/unl-map-js@0.1.5/lib/unl-map-js.js"></script><link href="https://unpkg.com/unl-map-js@0.1.5/lib/unl-map-js.css" rel="stylesheet" /><linkhref="https://unpkg.com/maplibre-gl@2.1.9/dist/maplibre-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>var map = new UnlSdk.Map({container: "map",apiKey: "YOUR-OWN-API-KEY",vpmId: "YOUR-OWN-VPM-ID",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>