缩放至线要素
点击线段时自动缩放和定位到线要素;
<!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; }
html, body, #map { height: 100%; }
.map-overlay {
position: absolute;
top: 10px;
right: 10px;
background: rgba(255, 255, 255, 0.9);
margin-right: 10px;
font-family: Arial, sans-serif;
overflow: auto;
border-radius: 3px;
padding: 10px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
line-height: 18px;
max-width: 300px;
}
.map-overlay h3 {
margin: 0 0 10px;
font-size: 16px;
border-bottom: 1px solid #ddd;
padding-bottom: 5px;
}
.map-overlay p {
font-size: 13px;
line-height: 1.5;
margin: 0 0 10px;
}
.line-info {
margin-top: 10px;
display: none;
}
.route-list {
margin-top: 10px;
}
.route-list button {
display: block;
margin-bottom: 5px;
padding: 5px 10px;
background: #4264fb;
color: white;
border: none;
border-radius: 3px;
cursor: pointer;
width: 100%;
text-align: left;
}
.route-list button:hover {
background: #3151c9;
}
</style>
</head>
<body>
<div id="map"></div>
<div class="map-overlay">
<h3>路线查看器</h3>
<p>
点击下方列表中的路线或直接点击地图上的线段以自动缩放到路线。
</p>
<div class="route-list">
<button id="route1">路线 1: 旧金山到洛杉矶</button>
<button id="route2">路线 2: 纽约到波士顿</button>
<button id="route3">路线 3: 芝加哥到底特律</button>
</div>
<div id="line-info" class="line-info">
<h3 id="line-title">路线信息</h3>
<p id="line-description">点击路线查看详情。</p>
<p>
距离: <span id="line-distance">--</span> 公里<br>
估计时间: <span id="line-time">--</span> 小时
</p>
</div>
</div>
<script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://api.maptiler.com/maps/streets/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
center: [-98.5795, 39.8283],
zoom: 3
});
map.addControl(new maplibregl.NavigationControl());
// 示例路线数据
const routes = {
route1: {
name: '旧金山到洛杉矶',
description: '沿着加州海岸线的美丽之旅',
distance: 616,
time: 6.5,
color: '#3887be',
coordinates: [
[-122.4194, 37.7749], // 旧金山
[-122.2, 36.9], // 沿海岸线
[-121.8, 36.6], // 蒙特雷
[-120.7, 35.3], // 圣路易斯-奥比斯波
[-119.7, 34.4], // 圣巴巴拉
[-118.2437, 34.0522] // 洛杉矶
]
},
route2: {
name: '纽约到波士顿',
description: '东北部的城市之旅',
distance: 348,
time: 4,
color: '#e55e5e',
coordinates: [
[-74.0060, 40.7128], // 纽约
[-73.1, 41.0], // 中间点
[-72.6, 41.3], // 新伦敦
[-71.4128, 41.8240], // 普罗维登斯
[-71.0589, 42.3601] // 波士顿
]
},
route3: {
name: '芝加哥到底特律',
description: '穿越美国中西部',
distance: 455,
time: 4.5,
color: '#6ebe8a',
coordinates: [
[-87.6298, 41.8781], // 芝加哥
[-86.9, 41.6], // 南湾
[-85.6, 42.3], // 卡拉马祖
[-84.5, 42.7], // 兰辛
[-83.0458, 42.3314] // 底特律
]
}
};
// 在地图加载后添加路线
map.on('load', () => {
// 为每条路线添加源和图层
for (const id in routes) {
const route = routes[id];
map.addSource(id, {
'type': 'geojson',
'data': {
'type': 'Feature',
'properties': {
'name': route.name,
'description': route.description,
'distance': route.distance,
'time': route.time,
'color': route.color
},
'geometry': {
'type': 'LineString',
'coordinates': route.coordinates
}
}
});
map.addLayer({
'id': id,
'type': 'line',
'source': id,
'layout': {
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': route.color,
'line-width': 8,
'line-opacity': 0.8
}
});
// 添加端点标记
map.addSource(`${id}-points`, {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'properties': { 'description': '起点' },
'geometry': {
'type': 'Point',
'coordinates': route.coordinates[0]
}
},
{
'type': 'Feature',
'properties': { 'description': '终点' },
'geometry': {
'type': 'Point',
'coordinates': route.coordinates[route.coordinates.length - 1]
}
}
]
}
});
map.addLayer({
'id': `${id}-points`,
'type': 'circle',
'source': `${id}-points`,
'paint': {
'circle-radius': 6,
'circle-color': route.color,
'circle-stroke-width': 2,
'circle-stroke-color': '#ffffff'
}
});
}
// 添加点击事件监听器 - 点击线路
for (const id in routes) {
map.on('click', id, (e) => {
zoomToLine(id);
showLineInfo(id);
});
// 当鼠标悬停在线路上时,更改光标样式
map.on('mouseenter', id, () => {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', id, () => {
map.getCanvas().style.cursor = '';
});
}
// 为按钮添加点击事件
document.getElementById('route1').addEventListener('click', () => {
zoomToLine('route1');
showLineInfo('route1');
});
document.getElementById('route2').addEventListener('click', () => {
zoomToLine('route2');
showLineInfo('route2');
});
document.getElementById('route3').addEventListener('click', () => {
zoomToLine('route3');
showLineInfo('route3');
});
});
// 函数:缩放到线要素
function zoomToLine(id) {
const source = map.getSource(id);
const coordinates = source._data.geometry.coordinates;
// 计算边界框
const bounds = coordinates.reduce((bounds, coord) => {
return bounds.extend(coord);
}, new maplibregl.LngLatBounds(coordinates[0], coordinates[0]));
// 缩放地图到线要素
map.fitBounds(bounds, {
padding: 60,
duration: 1000
});
}
// 函数:显示线要素信息
function showLineInfo(id) {
const route = routes[id];
const infoBox = document.getElementById('line-info');
// 显示信息框
infoBox.style.display = 'block';
// 更新信息内容
document.getElementById('line-title').textContent = route.name;
document.getElementById('line-description').textContent = route.description;
document.getElementById('line-distance').textContent = route.distance;
document.getElementById('line-time').textContent = route.time;
}
</script>
</body>
</html>