基于滚动位置飞行到特定位置
根据页面滚动位置将地图飞行到特定位置;
<!DOCTYPE html>
<html lang="en">
<head>
<title>基于滚动位置飞行到特定位置</title>
<meta property="og:description" content="根据页面滚动位置将地图飞行到特定位置" />
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.css' />
<script src='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.js'></script>
<style>
body { margin: 0; padding: 0; }
#map { top: 0; height: 100vh; width: 100%; position: fixed; z-index: -5; }
#features {
width: 50%;
margin: 0 auto;
font-family: sans-serif;
padding-top: 70vh;
}
section {
padding-bottom: 50vh;
opacity: 0.25;
border-bottom: 1px solid #ddd;
}
section.active {
opacity: 1;
}
section:last-child {
border-bottom: none;
margin-bottom: 100vh;
}
h3 {
position: sticky;
top: 0;
background: white;
padding: 0.5rem;
margin: 0;
border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
font-size: 24px;
}
p {
font-size: 16px;
line-height: 1.5;
margin-top: 10px;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="features">
<section id="baker" class="active">
<h3>贝克街 221B</h3>
<p>
2010年11月,我们于贝克街221B会见了夏洛克·福尔摩斯先生。他向我们讲述了一个离奇的案件,
涉及到一位来自美国的人,由于家族纠葛被追踪至伦敦。
</p>
</section>
<section id="aldgate">
<h3>奥尔德盖特</h3>
<p>
随后,调查使我们来到了奥尔德盖特东区,在这里我们找到了重要的线索,表明我们要找的美国人
曾在当地一家旅馆居住了一段时间。
</p>
</section>
<section id="london-bridge">
<h3>伦敦桥</h3>
<p>
线索指向伦敦桥。从收集到的信息来看,我们的美国人似乎准备离开英国,计划从伦敦桥附近的码头乘船出发。
</p>
</section>
<section id="woolwich">
<h3>伍尔维奇</h3>
<p>
事情发生了转折,我们的目标改变了路线,前往了伍尔维奇。原来他在这里有一位老朋友,可能在协助他逃亡。
</p>
</section>
<section id="gloucester">
<h3>格洛斯特路</h3>
<p>
经过几番周折,调查带领我们来到了肯辛顿的格洛斯特路。在这个安静的住宅区,我们发现了我们要找的人留下的痕迹。
</p>
</section>
<section id="caulfield-gardens">
<h3>考菲尔德花园</h3>
<p>
案件在考菲尔德花园达到了高潮。福尔摩斯在这里发现了一封信,揭示了案件背后错综复杂的家族秘密。
</p>
</section>
<section id="telegraph">
<h3>电报大楼</h3>
<p>
为了传递紧急消息,我们来到了电报大楼。福尔摩斯向美国发送了电报,确认了嫌疑人的身份和家族历史。
</p>
</section>
<section id="charing-cross">
<h3>查令十字</h3>
<p>
最终,我们在查令十字站逮捕了我们的美国人。案件圆满解决,福尔摩斯再次展示了他非凡的推理能力。
</p>
</section>
</div>
<script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://api.maptiler.com/maps/streets/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
center: [-0.15591514, 51.51830379],
zoom: 15.5,
bearing: 27,
pitch: 45
});
const chapters = {
'baker': {
bearing: 27,
center: [-0.15591514, 51.51830379],
zoom: 15.5,
pitch: 20
},
'aldgate': {
duration: 6000,
center: [-0.07571203, 51.51424049],
bearing: 150,
zoom: 15,
pitch: 0
},
'london-bridge': {
bearing: 90,
center: [-0.08533793, 51.50438536],
zoom: 13,
speed: 0.6,
pitch: 40
},
'woolwich': {
bearing: 90,
center: [0.05991101, 51.48752939],
zoom: 12.3
},
'gloucester': {
bearing: 45,
center: [-0.18335806, 51.49439521],
zoom: 15.3,
pitch: 20,
speed: 0.5
},
'caulfield-gardens': {
bearing: 180,
center: [-0.19684993, 51.5033856],
zoom: 12.3
},
'telegraph': {
bearing: 90,
center: [-0.10669358, 51.51433123],
zoom: 17.3,
pitch: 40
},
'charing-cross': {
bearing: 90,
center: [-0.12416858, 51.50779757],
zoom: 14.3,
pitch: 20
}
};
// 每次滚动事件中,检查哪个元素在屏幕上
window.onscroll = function() {
const chapterNames = Object.keys(chapters);
for (let i = 0; i < chapterNames.length; i++) {
const chapterName = chapterNames[i];
if (isElementOnScreen(chapterName)) {
setActiveChapter(chapterName);
break;
}
}
};
let activeChapterName = 'baker';
function setActiveChapter(chapterName) {
if (chapterName === activeChapterName) return;
map.flyTo(chapters[chapterName]);
document.getElementById(chapterName).setAttribute('class', 'active');
document.getElementById(activeChapterName).setAttribute('class', '');
activeChapterName = chapterName;
}
function isElementOnScreen(id) {
const element = document.getElementById(id);
const bounds = element.getBoundingClientRect();
return bounds.top < window.innerHeight && bounds.bottom > 0;
}
</script>
</body>
</html>