Fly to a Location Based on Scroll Position
Scroll-linked maps connect the page’s scroll position to the map camera by listening to the scroll event and mapping the scroll offset to a set of predefined locations. As the user scrolls through the page content, the map flies or eases to corresponding coordinates. Use this pattern for narrative journalism, travel guides, or any long-form content that uses a map to illustrate locations as the reader progresses through the story.
const API_KEY = 'YOUR_API_KEY';
const map = new maptoolkit.Map({
container: 'map',
apiKey: API_KEY,
style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
center: [11.39085, 47.27574],
zoom: 12,
interactive: false,
attributionControl: { compact: false }
});
const steps = document.querySelectorAll('.step');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
const [lng, lat] = el.dataset.center.split(',').map(Number);
const zoom = Number(el.dataset.zoom);
map.flyTo({ center: [lng, lat], zoom, essential: true });
}
});
}, { threshold: 0.5 });
steps.forEach(step => observer.observe(step));<!DOCTYPE html>
<html lang="en">
<head>
<title>Fly to a Location Based on Scroll Position - Maptoolkit Maps JS</title>
<meta property="og:description" content="Move the map camera as the user scrolls down the page." />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://unpkg.com/@maptoolkit/[email protected]/dist/maptoolkit.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@maptoolkit/[email protected]/dist/maptoolkit.css" />
<style>
body { margin: 0; padding: 0; }
#map { position: sticky; top: 0; width: 100%; height: 100vh; }
#story {
position: relative;
z-index: 1;
pointer-events: none;
}
.step {
height: 100vh;
display: flex;
align-items: center;
padding: 0 40px;
}
.step-inner {
background: rgba(255,255,255,0.9);
padding: 20px;
border-radius: 8px;
max-width: 300px;
pointer-events: auto;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="story">
<div class="step" data-center="11.39085,47.27574" data-zoom="12">
<div class="step-inner"><h3>Innsbruck</h3><p>Capital of Tyrol, nestled in the Alps at 574 m elevation.</p></div>
</div>
<div class="step" data-center="13.0550,47.8095" data-zoom="13">
<div class="step-inner"><h3>Salzburg</h3><p>Birthplace of Mozart and UNESCO World Heritage city.</p></div>
</div>
<div class="step" data-center="16.3738,48.2082" data-zoom="13">
<div class="step-inner"><h3>Vienna</h3><p>Austria's capital and cultural heart on the Danube.</p></div>
</div>
</div>
<script>
const API_KEY = 'YOUR_API_KEY';
const map = new maptoolkit.Map({
container: 'map',
apiKey: API_KEY,
style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
center: [11.39085, 47.27574],
zoom: 12,
interactive: false,
attributionControl: { compact: false }
});
const steps = document.querySelectorAll('.step');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
const [lng, lat] = el.dataset.center.split(',').map(Number);
const zoom = Number(el.dataset.zoom);
map.flyTo({ center: [lng, lat], zoom, essential: true });
}
});
}, { threshold: 0.5 });
steps.forEach(step => observer.observe(step));
</script>
</body>
</html>Use the prompt below with any LLM to get the same result. Make sure the Maptoolkit MCP server is connected first — check out AI Integration & MCP to get started.
Use the Maptoolkit Connector. Create a scrollytelling map starting at [11.39085, 47.27574] with zoom 12. As the user scrolls, fly to Innsbruck, Salzburg, and Vienna, each with a text panel describing the city.