Animate Camera Around a Point
Continuously rotate the map camera around a fixed point to create a smooth orbiting animation.
How It Works
The animation works by repeatedly calling map.easeTo() with an incremented bearing on each animation frame using requestAnimationFrame.
Basic Usage
javascript
let rotating = false;
let animationId = null;
function rotateCamera() {
if (!rotating) return;
// Increment bearing by a small amount each frame
map.easeTo({
bearing: map.getBearing() + 0.3,
duration: 0,
easing: (t) => t
});
// Request next frame
animationId = requestAnimationFrame(rotateCamera);
}
// Start rotation
function startRotation() {
rotating = true;
rotateCamera();
}
// Stop rotation
function stopRotation() {
rotating = false;
if (animationId) cancelAnimationFrame(animationId);
}Customization
javascript
// Faster rotation
map.easeTo({ bearing: map.getBearing() + 1.0, duration: 0 });
// Slower rotation
map.easeTo({ bearing: map.getBearing() + 0.1, duration: 0 });
// Rotate AND change pitch for a dynamic effect
map.easeTo({
bearing: map.getBearing() + 0.5,
pitch: 60,
duration: 0
});Complete Example
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
<script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
<style>
#map { height: 500px; width: 100%; }
.controls { margin-top: 10px; display: flex; gap: 8px; }
button { padding: 8px 16px; color: white; border: none; border-radius: 6px; cursor: pointer; }
#start-btn { background: #22c55e; }
#stop-btn { background: #ef4444; display: none; }
</style>
</head>
<body>
<div id="map"></div>
<div class="controls">
<button id="start-btn" onclick="startRotation()">▶ Start Rotation</button>
<button id="stop-btn" onclick="stopRotation()">⏹ Stop Rotation</button>
</div>
<script>
const map = new mapmetricsgl.Map({
container: 'map',
style: '<StyleFile_URL_with_Token>',
center: [2.349902, 48.852966],
zoom: 14,
pitch: 60,
bearing: 0
});
map.addControl(new mapmetricsgl.NavigationControl(), 'top-right');
let rotating = false;
let animationId = null;
function rotateCamera() {
if (!rotating) return;
map.easeTo({ bearing: map.getBearing() + 0.3, duration: 0, easing: t => t });
animationId = requestAnimationFrame(rotateCamera);
}
function startRotation() {
rotating = true;
document.getElementById('start-btn').style.display = 'none';
document.getElementById('stop-btn').style.display = 'inline-block';
rotateCamera();
}
function stopRotation() {
rotating = false;
if (animationId) cancelAnimationFrame(animationId);
document.getElementById('start-btn').style.display = 'inline-block';
document.getElementById('stop-btn').style.display = 'none';
}
</script>
</body>
</html>jsx
import React, { useEffect, useRef, useState } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
const AnimateCameraAround = () => {
const mapContainer = useRef(null);
const map = useRef(null);
const rotating = useRef(false);
const animationId = useRef(null);
const [isRotating, setIsRotating] = useState(false);
useEffect(() => {
if (map.current) return;
map.current = new mapmetricsgl.Map({
container: mapContainer.current,
style: '<StyleFile_URL_with_Token>',
center: [2.349902, 48.852966],
zoom: 14,
pitch: 60,
bearing: 0
});
map.current.addControl(new mapmetricsgl.NavigationControl(), 'top-right');
return () => {
rotating.current = false;
if (animationId.current) cancelAnimationFrame(animationId.current);
map.current?.remove();
map.current = null;
};
}, []);
const rotateCamera = () => {
if (!rotating.current) return;
map.current?.easeTo({ bearing: map.current.getBearing() + 0.3, duration: 0, easing: t => t });
animationId.current = requestAnimationFrame(rotateCamera);
};
const startRotation = () => {
rotating.current = true;
setIsRotating(true);
rotateCamera();
};
const stopRotation = () => {
rotating.current = false;
setIsRotating(false);
if (animationId.current) cancelAnimationFrame(animationId.current);
};
return (
<div>
<div ref={mapContainer} style={{ height: '500px', width: '100%' }} />
<div style={{ display: 'flex', gap: '8px', marginTop: '10px' }}>
{!isRotating ? (
<button onClick={startRotation} style={{ padding: '8px 16px', background: '#22c55e', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer' }}>
▶ Start Rotation
</button>
) : (
<button onClick={stopRotation} style={{ padding: '8px 16px', background: '#ef4444', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer' }}>
⏹ Stop Rotation
</button>
)}
</div>
</div>
);
};
export default AnimateCameraAround;For more information, visit the MapMetrics GitHub repository.