使用游戏控制导航地图
使用类似游戏的控制方式导航地图;
<!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%; }
</style>
</head>
<body>
<style>
#instructions {
position: absolute;
margin: 20px;
width: 240px;
top: 0;
bottom: 20%;
padding: 20px;
background-color: rgba(255, 255, 255, 0.8);
overflow-y: auto;
font-family: sans-serif;
font-size: 0.8em;
line-height: 1.5em;
}
</style>
<div id="map"></div>
<div id="instructions">
<h1>游戏控制</h1>
<p>使用键盘像在电子游戏中一样导航地图:</p>
<ul>
<li>W: 向前移动</li>
<li>A: 向左移动</li>
<li>S: 向后移动</li>
<li>D: 向右移动</li>
<li>↑: 提高视角</li>
<li>↓: 降低视角</li>
<li>←: 向左旋转视角</li>
<li>→: 向右旋转视角</li>
</ul>
</div>
<script>
const map = new maplibregl.Map({
container: 'map',
style:
'https://api.maptiler.com/maps/streets/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
center: [-117.1625, 32.7177],
zoom: 16,
pitch: 45,
bearing: 90
});
// 设置让3D效果更好的地图选项
map.on('style.load', () => {
map.setFog({
color: 'rgb(186, 210, 235)', // 薄雾的颜色
'high-color': 'rgb(36, 92, 223)', // 上部雾的颜色
'horizon-blend': 0.02 // 雾与天空之间的混合
});
});
// 添加导航控件
map.addControl(new maplibregl.NavigationControl());
// 设置运动的参数 - 调整这些值以更改动作的"感觉"
const options = {
movement: {
speed: 0.1, // 移动速度
pitch: 0.5 // 视角调整速度
},
rotation: {
speed: 1 // 旋转速度
}
};
// 初始化键盘状态
const keys = {};
// 当按键按下时
document.addEventListener('keydown', (e) => {
keys[e.code] = true;
});
// 当按键松开时
document.addEventListener('keyup', (e) => {
keys[e.code] = false;
});
function gameLoop() {
// 根据键盘状态执行操作
const map_bearing = map.getBearing();
const direction_bearing = map_bearing * (Math.PI / 180);
// 使用WASD移动
if (keys['KeyW']) {
// 向前移动 - 使用地图方位从而沿视线方向移动
const x = -Math.sin(direction_bearing) * options.movement.speed;
const y = -Math.cos(direction_bearing) * options.movement.speed;
map.panBy([x, y]);
}
if (keys['KeyS']) {
// 向后移动
const x = Math.sin(direction_bearing) * options.movement.speed;
const y = Math.cos(direction_bearing) * options.movement.speed;
map.panBy([x, y]);
}
if (keys['KeyA']) {
// 向左移动 - 左90度
const x = -Math.sin(direction_bearing + Math.PI / 2) * options.movement.speed;
const y = -Math.cos(direction_bearing + Math.PI / 2) * options.movement.speed;
map.panBy([x, y]);
}
if (keys['KeyD']) {
// 向右移动 - 右90度
const x = -Math.sin(direction_bearing - Math.PI / 2) * options.movement.speed;
const y = -Math.cos(direction_bearing - Math.PI / 2) * options.movement.speed;
map.panBy([x, y]);
}
// 使用箭头键控制视角和旋转
if (keys['ArrowLeft']) {
// 向左旋转
map.setBearing(map.getBearing() - options.rotation.speed);
}
if (keys['ArrowRight']) {
// 向右旋转
map.setBearing(map.getBearing() + options.rotation.speed);
}
if (keys['ArrowUp']) {
// 向上看(增加倾斜度)
const current_pitch = map.getPitch();
if (current_pitch < 70) {
map.setPitch(current_pitch + options.movement.pitch);
}
}
if (keys['ArrowDown']) {
// 向下看(减少倾斜度)
const current_pitch = map.getPitch();
if (current_pitch > 0) {
map.setPitch(current_pitch - options.movement.pitch);
}
}
// 持续运行游戏循环
requestAnimationFrame(gameLoop);
}
// 开始游戏循环
gameLoop();
</script>
</body>
</html>