同步多个地图的移动
同步多个地图的移动;
<!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 { height: 100%; }
.container {
display: flex;
flex-direction: column;
height: 100%;
}
.map-row {
display: flex;
flex: 1;
flex-direction: row;
width: 100%;
height: 50%;
}
.map {
flex: 1;
position: relative;
border: 1px solid #ccc;
box-sizing: border-box;
}
.map-label {
position: absolute;
top: 10px;
left: 10px;
background: rgba(255, 255, 255, 0.8);
padding: 5px 10px;
border-radius: 4px;
font-family: Arial, sans-serif;
font-weight: bold;
font-size: 14px;
z-index: 1;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
}
.control-panel {
position: absolute;
top: 10px;
right: 10px;
z-index: 10;
background: white;
padding: 10px;
border-radius: 4px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
font-family: Arial, sans-serif;
min-width: 200px;
}
.control-panel h3 {
margin: 0 0 10px 0;
font-size: 16px;
}
.control-panel label {
display: block;
margin-bottom: 8px;
}
button {
background: #3887be;
color: white;
border: none;
padding: 5px 10px;
border-radius: 3px;
cursor: pointer;
margin-right: 5px;
margin-bottom: 5px;
}
button:hover {
background: #2d6a94;
}
.toggle-group {
margin-bottom: 15px;
}
.info-text {
font-size: 12px;
color: #666;
margin-top: 15px;
}
</style>
</head>
<body>
<div class="container">
<div class="map-row">
<div id="map1" class="map">
<div class="map-label">街道地图</div>
</div>
<div id="map2" class="map">
<div class="map-label">卫星地图</div>
</div>
</div>
<div class="map-row">
<div id="map3" class="map">
<div class="map-label">地形地图</div>
</div>
<div id="map4" class="map">
<div class="map-label">深色地图</div>
</div>
</div>
</div>
<div class="control-panel">
<h3>同步控制</h3>
<div class="toggle-group">
<label>
<input type="checkbox" id="sync-movement" checked>
同步移动
</label>
<label>
<input type="checkbox" id="sync-zoom" checked>
同步缩放
</label>
<label>
<input type="checkbox" id="sync-pitch" checked>
同步俯仰角
</label>
<label>
<input type="checkbox" id="sync-bearing" checked>
同步方位角
</label>
</div>
<div>
<button id="fly-to-london">伦敦</button>
<button id="fly-to-nyc">纽约</button>
<button id="fly-to-sf">旧金山</button>
<button id="fly-to-tokyo">东京</button>
</div>
<div class="info-text">
此示例演示如何同步多个地图的视图。当一个地图移动时,其他地图也会相应地移动。
</div>
</div>
<script>
// 创建四个不同样式的地图
const map1 = new maplibregl.Map({
container: 'map1',
style: 'https://api.maptiler.com/maps/streets/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
center: [0, 0],
zoom: 2
});
const map2 = new maplibregl.Map({
container: 'map2',
style: 'https://api.maptiler.com/maps/hybrid/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
center: [0, 0],
zoom: 2
});
const map3 = new maplibregl.Map({
container: 'map3',
style: 'https://api.maptiler.com/maps/outdoor/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
center: [0, 0],
zoom: 2
});
const map4 = new maplibregl.Map({
container: 'map4',
style: 'https://api.maptiler.com/maps/streets-dark/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
center: [0, 0],
zoom: 2
});
// 将所有地图存储在一个数组中
const maps = [map1, map2, map3, map4];
// 添加导航控件到每个地图
maps.forEach(map => {
map.addControl(new maplibregl.NavigationControl(), 'top-right');
});
// 获取同步设置控件
const syncMovement = document.getElementById('sync-movement');
const syncZoom = document.getElementById('sync-zoom');
const syncPitch = document.getElementById('sync-pitch');
const syncBearing = document.getElementById('sync-bearing');
// 避免无限循环的标志
let moveFlag = false;
let zoomFlag = false;
let pitchFlag = false;
let bearingFlag = false;
// 同步函数
function syncMaps(mainMap) {
return function() {
if (moveFlag || zoomFlag || pitchFlag || bearingFlag) return;
const center = mainMap.getCenter();
const zoom = mainMap.getZoom();
const pitch = mainMap.getPitch();
const bearing = mainMap.getBearing();
// 设置标志以避免无限循环
moveFlag = true;
zoomFlag = true;
pitchFlag = true;
bearingFlag = true;
maps.forEach(otherMap => {
if (otherMap !== mainMap) {
if (syncMovement.checked) {
otherMap.setCenter(center);
}
if (syncZoom.checked) {
otherMap.setZoom(zoom);
}
if (syncPitch.checked) {
otherMap.setPitch(pitch);
}
if (syncBearing.checked) {
otherMap.setBearing(bearing);
}
}
});
// 重置标志
setTimeout(() => {
moveFlag = false;
zoomFlag = false;
pitchFlag = false;
bearingFlag = false;
}, 10);
};
}
// 将同步功能附加到每个地图
maps.forEach(map => {
map.on('move', syncMaps(map));
});
// 预设位置
const locations = {
'london': {
center: [-0.1278, 51.5074],
zoom: 12,
pitch: 45,
bearing: 15
},
'nyc': {
center: [-74.0060, 40.7128],
zoom: 12,
pitch: 50,
bearing: -20
},
'sf': {
center: [-122.4194, 37.7749],
zoom: 13,
pitch: 60,
bearing: 30
},
'tokyo': {
center: [139.6503, 35.6762],
zoom: 12,
pitch: 40,
bearing: 0
}
};
// 飞行按钮事件
document.getElementById('fly-to-london').addEventListener('click', () => {
map1.flyTo(locations.london);
});
document.getElementById('fly-to-nyc').addEventListener('click', () => {
map1.flyTo(locations.nyc);
});
document.getElementById('fly-to-sf').addEventListener('click', () => {
map1.flyTo(locations.sf);
});
document.getElementById('fly-to-tokyo').addEventListener('click', () => {
map1.flyTo(locations.tokyo);
});
</script>
</body>
</html>