Leaflet.js Animations — Smooth Map Motion and Transitions
In this tutorial, you will learn about Leaflet.js Animations. We cover key concepts, practical examples, and best practices to help you master this topic.
Leaflet.js animations create smooth transitions for map movement, marker motion, and feature visualization using built-in animation methods and requestAnimationFrame.
What You'll Learn
By the end of this guide, you will animate map pan and zoom transitions, fly to coordinates with custom duration and easing, animate markers along paths, create pulsing marker effects, and animate GeoJSON features.
Animated Pan
map.panTo([40.7128, -74.0060], {
animate: true,
duration: 2.0
});
Fly To
map.flyTo([51.505, -0.09], 13, {
animate: true,
duration: 3,
easeLinearity: 0.3
});
Animated Marker
function moveMarker(marker, targetLatLng, duration) {
var start = marker.getLatLng();
var startTime = performance.now();
function animate(time) {
var elapsed = (time - startTime) / 1000;
var t = Math.min(elapsed / duration, 1);
var lat = start.lat + (targetLatLng.lat - start.lat) * t;
var lng = start.lng + (targetLatLng.lng - start.lng) * t;
marker.setLatLng([lat, lng]);
if (t < 1) requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
}
Pulsing Marker
var pulsingIcon = L.divIcon({
className: 'pulsing-marker',
html: '<div class="pulse"></div>',
iconSize: [30, 30]
});
L.marker([40.7128, -74.0060], { icon: pulsingIcon }).addTo(map);
// CSS:
// .pulsing-marker .pulse { width: 20px; height: 20px; border-radius: 50%; background: #ff6b35; animation: pulse 1.5s infinite; }
// @keyframes pulse { 0% { transform: scale(1); opacity: 1; } 100% { transform: scale(2); opacity: 0; } }
Common Mistakes
1. Not Using requestAnimationFrame
setInterval for animations causes jank. Use requestAnimationFrame for smooth 60fps motion.
2. Disabling Map Interaction During Animation
Set noMoveStart: true on panTo to prevent interaction during animation.
3. Long Duration Values
Duration over 5 seconds feels slow. Use 1-3 seconds for most animations.
4. Interrupting Animation
Calling panTo while an animation is running cancels the previous one. Check map._animating before starting.
5. No Easing
Linear motion looks unnatural. Leaflet uses easeInOut by default. Set easeLinearity for custom easing.
Practice Questions
Q1: What method animates the map to a new center? A: map.panTo(latlng, { animate: true, duration: seconds }).
Q2: What is the difference between panTo and flyTo? A: flyTo animates both center and zoom simultaneously with a dramatic flight effect.
Q3: How do you animate a marker along a path? A: Use requestAnimationFrame and update marker.setLatLng each frame with interpolated coordinates.
Q4: How do you create a pulsing marker? A: Use L.divIcon with CSS keyframe animations on the icon element.
Q5: How do you cancel an animation? A: Leaflet panTo animation auto-cancels on new map interaction. Custom animations need a cancel flag.
Challenge: Build a map tour that flies to 5 major world cities sequentially with a 2-second delay between each. Add a progress indicator.
FAQ
Try It Yourself
Build a map with a moving marker.
<!DOCTYPE html>
<html>
<head>
<title>Animation Demo</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9/dist/leaflet.js"></script>
<style>
.moving-marker { background: #ff6b35; border: 3px solid #fff; border-radius: 50%; width: 16px; height: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.3); }
</style>
</head>
<body style="font-family:sans-serif;padding:20px;">
<h2>Animated Marker</h2>
<button onclick="flyToNYC()">Fly to NYC</button>
<button onclick="animateMarker()">Move Marker</button>
<div id="map" style="height:400px;border-radius:8px;margin-top:8px;"></div>
<script>
var map = L.map('map').setView([40.7128, -74.0060], 12);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OSM'
}).addTo(map);
var marker = L.marker([40.7128, -74.0060], {
icon: L.divIcon({ className: 'moving-marker', iconSize: [16, 16] })
}).addTo(map);
function flyToNYC() {
map.flyTo([40.7128, -74.0060], 14, {
duration: 2,
easeLinearity: 0.5
});
}
function animateMarker() {
var target = L.latLng(
40.7128 + (Math.random() - 0.5) * 0.05,
-74.0060 + (Math.random() - 0.5) * 0.05
);
var start = marker.getLatLng();
var startTime = performance.now();
var duration = 2;
function step(time) {
var t = Math.min((time - startTime) / (duration * 1000), 1);
var lat = start.lat + (target.lat - start.lat) * t;
var lng = start.lng + (target.lng - start.lng) * t;
marker.setLatLng([lat, lng]);
if (t < 1) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
</script>
</body>
</html>
What's Next
Build a complete map project.
Project — Complete map project.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro