Markers animation
You can animate markers on the map:
- Moving along a circle.
- Jumping (up and down movement).
- Moving along the specified coordinates. Additionally, you can add CSS marker animation.
- Animation of the traveled path using a Polyline.
- Animation of the HTML marker using Lottie.
To animate a marker, first add a Marker object to the map and specify the coordinates of the marker center:
const marker = new mapgl.Marker(map, {
coordinates: [55.31878, 25.23584],
});
Movement along a circle
The animation of a marker moving around a specified point is performed by changing the coordinates of the marker along the circle. New coordinates are calculated based on the current time and the rotation angle.
To add the animation of the movement along a circle, use the animateCircle
function:
function animateCircle(marker, centerCoords, radius, duration) {
const startTime = performance.now();
function frame(time) {
const elapsed = (time - startTime) % duration; // Time elapsed since the start of the current animation iteration
const angle = (2 * Math.PI * elapsed) / duration; // Current angle in radians
const newCoords = [
centerCoords[0] + radius * Math.cos(angle), // Calculating longitude
centerCoords[1] + radius * Math.sin(angle), // Calculating latitude
];
marker.setCoordinates(newCoords); // Setting the new marker coordinates
requestAnimationFrame(frame); // Scheduling the next frame
}
requestAnimationFrame(frame);
}
// Calling the animation function
animateCircle(marker, [55.31878, 25.23584], 0.01, 5000);
Specify the following parameters for the animateCircle
function:
marker
: marker object to animate.centerCoords
: coordinates of the circle center in the[longitude, latitude]
format.radius
: radius of the circle in geographic coordinates (in degrees).duration
: duration of one full revolution in milliseconds.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>2GIS Map API</title>
<style>
html,
body,
#container {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<script>
const map = new mapgl.Map('container', {
center: [55.323, 25.235],
zoom: 10.5,
key: 'Your API access key',
});
const marker = new mapgl.Marker(map, {
coordinates: [55.323, 25.235],
});
const centerCoords = [55.323, 25.235];
const radius = 0.1;
const duration = 5000;
function animateMarkerInCircle(marker, centerCoords, radius, duration) {
const startTime = performance.now();
function frame(time) {
const elapsed = (time - startTime) % duration;
const angle = (2 * Math.PI * elapsed) / duration;
const newCoords = [
centerCoords[0] + radius * Math.cos(angle),
centerCoords[1] + radius * Math.sin(angle),
];
marker.setCoordinates(newCoords);
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
}
animateMarkerInCircle(marker, centerCoords, radius, duration);
</script>
</body>
</html>
Jumping
The jumping animation allows a marker to move up and down, creating a bounce effect.
To perform the animation, the vertical offset of the marker is calculated relatively to its base coordinates. To make the jump look the same regardless of the scale and correct when the camera position changes, the current map scale is considered.
To add the jumping animation, use the animateJump
function:
function animateJump(marker, map, baseCoords, amplitude, duration) {
const startTime = performance.now();
function frame(time) {
const elapsed = (time - startTime) % duration; // Time elapsed since the start of the current animation iteration
const bounce = Math.sin((2 * Math.PI * elapsed) / duration) * amplitude; // Jump height
// Converting geographic coordinates to pixel coordinates
const basePixelCoords = map.project(baseCoords);
// Applying Y-axis (vertical) offset in pixels
const newPixelCoords = [
basePixelCoords[0], // X remains unchanged
basePixelCoords[1] - bounce, // Decreasing Y for jumping up
];
// Converting pixel coordinates back to geographic coordinates
const newGeoCoords = map.unproject(newPixelCoords);
// Setting the new marker coordinates
marker.setCoordinates(newGeoCoords);
requestAnimationFrame(frame); // Scheduling the next animation frame
}
requestAnimationFrame(frame);
}
// Calling the animation function
animateJump(marker, map, [55.31878, 25.23584], 20, 1000);
Specify the following parameters for the animateJump
function:
marker
: marker object to animate.map
: map object used for coordinate transformation.baseCoords
: initial coordinates of the marker in the[longitude, latitude]
format.amplitude
: jump amplitude (height of movement) in pixels.duration
: duration of one full jump (up and down) in milliseconds.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>2GIS Map API</title>
<style>
html,
body,
#container {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<script>
const map = new mapgl.Map('container', {
center: [55.323, 25.235],
zoom: 10.5,
key: 'Your API access key',
});
const marker = new mapgl.Marker(map, {
coordinates: [55.323, 25.235],
});
const centerCoords = [55.323, 25.235];
const radius = 0.1;
const duration = 5000;
function jumpMarkerAnimation(marker, map, baseCoords, amplitude, duration) {
const startTime = performance.now();
function frame(time) {
const elapsed = (time - startTime) % duration;
const bounce = Math.sin((2 * Math.PI * elapsed) / duration) * amplitude;
const basePixelCoords = map.project(baseCoords);
const newPixelCoords = [
basePixelCoords[0],
basePixelCoords[1] - bounce,
];
const newGeoCoords = map.unproject(newPixelCoords);
marker.setCoordinates(newGeoCoords);
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
}
jumpMarkerAnimation(marker, map, [55.323, 25.235], 20, 1000);
</script>
</body>
</html>
Movement along coordinates
Animation of movement along coordinates is performed by changing the geographical coordinates of the marker.
To add the animation of the movement along the specified route, use the animateTravel
function:
// Function for interpolating between two points
function interpolateCoordinates(coord1, coord2, t) {
return [coord1[0] + (coord2[0] - coord1[0]) * t, coord1[1] + (coord2[1] - coord1[1]) * t];
}
function animateTravel(marker, route, durationPerSegment) {
let segmentIndex = 0;
function animateSegment(startTime) {
const elapsedTime = performance.now() - startTime;
const t = elapsedTime / durationPerSegment; // Percentage of segment completion
if (t < 1) {
// Interpolating coordinates
const newCoords = interpolateCoordinates(
route[segmentIndex],
route[segmentIndex + 1],
t,
);
marker.setCoordinates(newCoords);
// Continuing animation of the current segment
requestAnimationFrame(() => animateSegment(startTime));
} else {
// Moving to the next segment
segmentIndex++;
if (segmentIndex < route.length - 1) {
animateSegment(performance.now());
} else {
// Looping the route
segmentIndex = 0;
animateSegment(performance.now());
}
}
}
// Starting the animation of the first segment
if (route.length > 1) {
animateSegment(performance.now());
}
}
// Calling the animation function
const durationPerSegment = 2000;
animateTravel(marker, route, durationPerSegment);
Specify the following parameters for the animateTravel
function:
marker
: marker object to animate.route
: array of route coordinates in the[longitude, latitude]
format.durationPerSegment
: duration of each segment in milliseconds.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>2GIS Map API - Courier Animation</title>
<style>
html,
body,
#container {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<script>
const map = new mapgl.Map('container', {
center: [55.280, 25.249],
zoom: 14,
key: 'Your API access key',
});
const route = `55.280324 25.249851,55.272991 25.239421,55.278568 25.235182,55.284862 25.246507,55.280324 25.249851`.split(',')
.map(pair => pair.split(' ').map(Number));
const marker = new mapgl.Marker(map, {
coordinates: route[0],
icon: 'https://disk.2gis.com/styles/assets/icons/poi_cars-66605ef515e3adca7dea4e3f1bac00195e250a1250a5bf9e313708cb25fd1467.svg',
size: [20,20],
});
function interpolateCoordinates(coord1, coord2, t) {
return [
coord1[0] + (coord2[0] - coord1[0]) * t,
coord1[1] + (coord2[1] - coord1[1]) * t,
];
}
function animateCourier(marker, route, durationPerSegment) {
let segmentIndex = 0;
function animateSegment(startTime) {
const elapsedTime = performance.now() - startTime;
const t = elapsedTime / durationPerSegment;
if (t < 1) {
// Интерполируем координаты
const newCoords = interpolateCoordinates(
route[segmentIndex],
route[segmentIndex + 1],
t
);
marker.setCoordinates(newCoords);
requestAnimationFrame(() => animateSegment(startTime));
} else {
segmentIndex++;
if (segmentIndex < route.length - 1) {
animateSegment(performance.now());
} else {
segmentIndex = 0;
animateSegment(performance.now());
}
}
}
if (route.length > 1) {
animateSegment(performance.now());
}
}
const durationPerSegment = 2000;
animateCourier(marker, route, durationPerSegment);
window.addEventListener('unload', () => map.destroy());
</script>
</body>
</html>
Additionally, you can add CSS marker animation.
Movement along coordinates with CSS animation
In addition to the animation of marker movement along the specified route coordinates, you can animate the HTML marker using CSS:
-
Create a CSS animation, for example:
<style> html, body, #container { margin: 0; width: 100%; height: 100%; overflow: hidden; } .marker_container { position: relative; width: 40px; height: 40px; } .marker_container::before { content: ''; position: absolute; top: 10px; left: 10px; transform: translate(-50%, -50%); width: 80px; height: 80px; border-radius: 50%; background: radial-gradient( closest-side, rgba(255, 165, 0, 0.8), rgba(255, 69, 0, 0.5), transparent ); animation: firePulse 1s infinite ease-in-out; } @keyframes firePulse { 0% { transform: translate(-50%, -50%) scale(1); opacity: 1; } 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.7; } 100% { transform: translate(-50%, -50%) scale(1); opacity: 1; } } .wave { position: absolute; top: 10px; left: 10px; width: 10px; height: 10px; background: rgba(0, 0, 255, 0.5); border-radius: 50%; transform: translate(-50%, -50%); animation: waveAnimation 2s infinite; } @keyframes waveAnimation { 0% { transform: translate(-50%, -50%) scale(1); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(5); opacity: 0; } } </style>
-
Create an HTML marker. The route-based animation is performed by changing the geographical coordinates of the marker:
const htmlMarker = new mapgl.HtmlMarker(map, { coordinates: [55.323, 25.235], html: '<div class="marker_container"><div class="wave"></div><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 50 50">\n' + ' <circle cx="25" cy="25" r="25" fill="white"/>\n' + '</svg></div>\n', });
-
Add the animation of the movement along coordinates using the
animateTravel
function:// Function for interpolating between two points function interpolateCoordinates(coord1, coord2, t) { return [coord1[0] + (coord2[0] - coord1[0]) * t, coord1[1] + (coord2[1] - coord1[1]) * t]; } function animateTravel(htmlMarker, route, durationPerSegment) { let segmentIndex = 0; function animateSegment(startTime) { const elapsedTime = performance.now() - startTime; const t = elapsedTime / durationPerSegment; // Percentage of segment completion if (t < 1) { // Interpolating coordinates const newCoords = interpolateCoordinates( route[segmentIndex], route[segmentIndex + 1], t, ); htmlMarker.setCoordinates(newCoords); // Continuing animation of the current segment requestAnimationFrame(() => animateSegment(startTime)); } else { // Moving to the next segment segmentIndex++; if (segmentIndex < route.length - 1) { animateSegment(performance.now()); } else { // Looping the route segmentIndex = 0; animateSegment(performance.now()); } } } // Starting the animation of the first segment if (route.length > 1) { animateSegment(performance.now()); } } // Calling the animation function const durationPerSegment = 2000; animateTravel(htmlMarker, route, durationPerSegment);
Specify the following parameters for the
animateTravel
function:htmlMarker
: HTML marker object to animate (created on step 2).route
: array of route coordinates in the[longitude, latitude]
format.durationPerSegment
: duration of each segment in milliseconds.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>2GIS Map API - Courier CSS Animation</title>
<style>
html,
body,
#container {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.marker_container {
position: relative;
width: 40px;
height: 40px;
}
.marker_container::before {
content: '';
position: absolute;
top: 10px;
left: 10px;
transform: translate(-50%, -50%);
width: 80px;
height: 80px;
border-radius: 50%;
background: radial-gradient(closest-side, rgba(255, 165, 0, 0.8), rgba(255, 69, 0, 0.5), transparent);
animation: firePulse 1s infinite ease-in-out;
}
@keyframes firePulse {
0% {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}
50% {
transform: translate(-50%, -50%) scale(1.2);
opacity: 0.7;
}
100% {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}
}
.wave {
position: absolute;
top: 10px;
left: 10px;
width: 10px;
height: 10px;
background: rgba(0, 0, 255, 0.5);
border-radius: 50%;
transform: translate(-50%, -50%);
animation: waveAnimation 2s infinite;
}
@keyframes waveAnimation {
0% {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}
100% {
transform: translate(-50%, -50%) scale(5);
opacity: 0;
}
}
</style>
</head>
<body>
<div id="container"></div>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<script>
const map = new mapgl.Map('container', {
center: [55.280, 25.249],
zoom: 14,
key: 'Your API access key',
});
const route = `55.280324 25.249851,55.272991 25.239421,55.278568 25.235182,55.283162 25.246507,55.280324 25.249851`.split(',')
.map(pair => pair.split(' ').map(Number));
const htmlMarker = new mapgl.HtmlMarker(map, {
coordinates: [55.323, 25.235],
html: '<div class="marker_container"><div class="wave"></div><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 50 50">\n' +
' <circle cx="25" cy="25" r="25" fill="white"/>\n' +
'</svg></div>\n',
});
function interpolateCoordinates(coord1, coord2, t) {
return [
coord1[0] + (coord2[0] - coord1[0]) * t,
coord1[1] + (coord2[1] - coord1[1]) * t,
];
}
function animateCourier(marker, route, durationPerSegment) {
let segmentIndex = 0;
function animateSegment(startTime) {
const elapsedTime = performance.now() - startTime;
const t = elapsedTime / durationPerSegment;
if (t < 1) {
const newCoords = interpolateCoordinates(
route[segmentIndex],
route[segmentIndex + 1],
t
);
marker.setCoordinates(newCoords);
requestAnimationFrame(() => animateSegment(startTime));
} else {
segmentIndex++;
if (segmentIndex < route.length - 1) {
animateSegment(performance.now());
} else {
segmentIndex = 0;
animateSegment(performance.now());
}
}
}
if (route.length > 1) {
animateSegment(performance.now());
}
}
const durationPerSegment = 2000;
animateCourier(htmlMarker, route, durationPerSegment);
window.addEventListener('unload', () => map.destroy());
</script>
</body>
</html>
Animation of the traveled path
You can animate the movement of an HTML marker along a specified route: show the traveled path as a line on the map and add marker animation as a pulsating circle using the HTML Canvas element. To do this:
-
Specify the marker route as an array of geocoordinates. To make the route closed, the end marker coordinate must match the start coordinate. For example:
// Marker route const path = [ [55.27075, 25.20483], [55.26782, 25.20061], [55.26526, 25.19762], [55.26296, 25.19486], [55.25959, 25.19147], [55.26165, 25.18888], [55.26508, 25.18634], [55.27168, 25.18758], [55.27554, 25.18448], [55.28022, 25.1873], [55.28402, 25.19192], [55.2895, 25.19491], [55.28533, 25.19751], [55.28059, 25.19982], [55.27648, 25.20201], [55.27305, 25.20393], [55.27075, 25.20483], // Route closes at the start point ];
-
Specify the marker speed in m/s for each route segment:
// Speed in m/s for each segment const segmentSpeedsMps = [45, 25, 15, 15, 30, 30, 30, 20, 30, 30, 20, 30, 15, 20, 23, 45];
-
Add functions to calculate the distance and duration of route segments:
// Function to calculate arc length by geocoordinates in meters function getDistance([lon1, lat1], [lon2, lat2]) { ... } // Calculate duration for each segment const segmentDurationsMs = path.slice(0, -1).map((_, i) => { const dist = getDistance(path[i], path[i + 1]); const speed = segmentSpeedsMps[i]; // m/s return (dist / speed) * 1000; // ms });
-
Create a
canvas
for the pulsating circle, which is used as HtmlMarkerOptions:// Create canvas for pulsating circle const canvas = document.createElement('canvas'); canvas.width = 80; canvas.height = 80; canvas.style.position = 'absolute'; canvas.style.transform = 'translate(-50%, -50%)'; const ctx = canvas.getContext('2d');
-
Add a function to draw the pulsating circle using CanvasRenderingContext2D:
// Function to draw pulsating circle function drawPulse(radius) { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath(); ctx.arc(40, 40, radius, 0, Math.PI * 2); ctx.fillStyle = 'rgba(206,56,56,0.4)'; ctx.fill(); ctx.beginPath(); ctx.arc(40, 40, 14, 0, Math.PI * 2); ctx.fillStyle = 'rgba(206,56,56,0.8)'; ctx.fill(); }
Instead of
canvas
, you can create the animation using CSS: see the CSS animation example. -
Create an HTML marker that displays the
canvas
on the map:// HTML marker with animated canvas const htmlMarker = new mapgl.HtmlMarker(map, { coordinates: path[0], html: canvas, zIndex: 100, });
-
Add the animation of the traveled path of the marker using a Polyline and the
animate()
function, which is called during frame rendering:// Function for interpolating between two points function interpolateCoords(a, b, t) { return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t]; } let index = 0; let passedCoords = [path[0]]; let polylines = []; let startTime = performance.now(); function destroyPolylines() { polylines.forEach((p) => p.destroy()); polylines = []; } function animate() { // Circle pulsation const animRadius = 18 + 9 * (0.5 + 0.5 * Math.sin(Date.now() / 250)); drawPulse(animRadius); // Current time on the segment const now = performance.now(); const duration = segmentDurationsMs[index]; const t = Math.min((now - startTime) / duration, 1); const newCoord = interpolateCoords(path[index], path[index + 1], t); htmlMarker.setCoordinates(newCoord); // Draw traveled route using Polyline const updatedPassed = passedCoords.slice(); updatedPassed.push(newCoord); destroyPolylines(); polylines.push( new mapgl.Polyline(map, { coordinates: updatedPassed, color: '#ce3838', width: 5, }), ); if (t < 1) { requestAnimationFrame(animate); } else { // Move to the next segment index++; if (index >= path.length - 1) { // Restart at the end of the route index = 0; passedCoords = [path[0]]; destroyPolylines(); } else { passedCoords.push(path[index]); } startTime = performance.now(); // Calling the animate() during frame rendering requestAnimationFrame(animate); } } // Calling the animation function animate();
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>2GIS Map API - Pulsating circle along the route with a path line</title>
<style>
html, body, #container {
margin: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<script>
const map = new mapgl.Map('container', {
center: [55.275, 25.196],
zoom: 13,
key: 'Your API access key',
});
const path = [
[55.27075, 25.20483],
[55.26782, 25.20061],
[55.26526, 25.19762],
[55.26296, 25.19486],
[55.25959, 25.19147],
[55.26165, 25.18888],
[55.26508, 25.18634],
[55.27168, 25.18758],
[55.27554, 25.18448],
[55.28022, 25.18730],
[55.28402, 25.19192],
[55.28950, 25.19491],
[55.28533, 25.19751],
[55.28059, 25.19982],
[55.27648, 25.20201],
[55.27305, 25.20393],
[55.27075, 25.20483],
];
const segmentSpeedsMps = [
45,
25,
15,
15,
30,
30,
30,
20,
30,
30,
20,
30,
15,
20,
23,
45,
];
function getDistance([lon1, lat1], [lon2, lat2]) {
const R = 6371000; // Радиус земли, м
const φ1 = lat1 * Math.PI/180;
const φ2 = lat2 * Math.PI/180;
const Δφ = (lat2 - lat1) * Math.PI/180;
const Δλ = (lon2 - lon1) * Math.PI/180;
const a = Math.sin(Δφ/2)*Math.sin(Δφ/2) +
Math.cos(φ1)*Math.cos(φ2) *
Math.sin(Δλ/2)*Math.sin(Δλ/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
const segmentDurationsMs = path.slice(0, -1).map((_, i) => {
const dist = getDistance(path[i], path[i + 1]);
const speed = segmentSpeedsMps[i]; // м/с
return (dist / speed) * 1000; // мс
});
const canvas = document.createElement('canvas');
canvas.width = 80;
canvas.height = 80;
canvas.style.position = 'absolute';
canvas.style.transform = 'translate(-50%, -50%)';
const ctx = canvas.getContext('2d');
function drawPulse(radius) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(40, 40, radius, 0, Math.PI*2);
ctx.fillStyle = 'rgba(206,56,56,0.4)';
ctx.fill();
ctx.beginPath();
ctx.arc(40, 40, 14, 0, Math.PI*2);
ctx.fillStyle = 'rgba(206,56,56,0.8)';
ctx.fill();
}
const htmlMarker = new mapgl.HtmlMarker(map, {
coordinates: path[0],
html: canvas,
zIndex: 100,
});
function interpolateCoords(a, b, t) {
return [
a[0] + (b[0] - a[0]) * t,
a[1] + (b[1] - a[1]) * t,
];
}
let index = 0;
let passedCoords = [path[0]];
let polylines = [];
let startTime = performance.now();
function destroyPolylines() {
polylines.forEach(p => p.destroy());
polylines = [];
}
function animate() {
const animRadius = 18 + 9 * (0.5 + 0.5 * Math.sin(Date.now() / 250));
drawPulse(animRadius);
const now = performance.now();
const duration = segmentDurationsMs[index];
const t = Math.min((now - startTime) / duration, 1);
const newCoord = interpolateCoords(path[index], path[index + 1], t);
htmlMarker.setCoordinates(newCoord);
const updatedPassed = passedCoords.slice();
updatedPassed.push(newCoord);
destroyPolylines();
polylines.push(
new mapgl.Polyline(map, {
coordinates: updatedPassed,
color: '#ce3838',
width: 5,
})
);
if (t < 1) {
requestAnimationFrame(animate);
} else {
index++;
if (index >= path.length - 1) {
index = 0;
passedCoords = [path[0]];
destroyPolylines();
} else {
passedCoords.push(path[index]);
}
startTime = performance.now();
requestAnimationFrame(animate);
}
}
animate();
</script>
</body>
</html>
Animation using Lottie
You can animate an HTML marker using Lottie:
-
Add Lottie:
<script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.0/lottie.min.js"></script>
-
Create an HTML marker:
const markerHtml = ` <div class="marker_container"> <div class="lottie_animation" id="lottie"></div> </div> `; const htmlMarker = new mapgl.HtmlMarker(map, { coordinates: [55.280324, 25.249851], html: markerHtml, });
-
Create a Lottie animation:
// Using MutationObserver to track the appearance of the element // Alternatively, you can use setTimeout with a value of 0 const observer = new MutationObserver(() => { const lottieContainer = document.getElementById('lottie'); if (lottieContainer) { observer.disconnect(); // Stop observing once the element is found lottie.loadAnimation({ container: lottieContainer, // Container ID renderer: 'svg', loop: true, autoplay: true, path: '<your>.json', // Path to the JSON file }); } }); observer.observe(document.body, { childList: true, subtree: true });
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.0/lottie.min.js"></script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>2GIS Map API - Lottie Animation</title>
<style>
html, body, #container {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.marker_container {
right: 20px;
bottom: 20px;
position: relative;
width: 40px;
height: 40px;
}
.lottie_animation {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<script>
const map = new mapgl.Map('container', {
center: [55.280, 25.249],
zoom: 14,
key: 'Your API access key',
});
const markerHtml = `
<div class="marker_container">
<div class="lottie_animation" id="lottie"></div>
</div>
`;
const htmlMarker = new mapgl.HtmlMarker(map, {
coordinates: [55.27993, 25.24349],
html: markerHtml,
});
const observer = new MutationObserver(() => {
const lottieContainer = document.getElementById('lottie');
if (lottieContainer) {
observer.disconnect();
lottie.loadAnimation({
container: lottieContainer,
renderer: 'svg',
loop: true,
autoplay: true,
path: 'https://lottie.host/7401522f-2d8b-4049-ad18-eb0edb6af224/CE9lFrNlEH.json',
});
}
});
observer.observe(document.body, { childList: true, subtree: true });
window.addEventListener('unload', () => map.destroy());
</script>
</body>
</html>