📌 学习目标
- 掌握添加实时数据的实现方法
- 理解相关API的使用
- 能够独立完成类似功能开发
🎯 核心概念
向地图添加实时数据流。
💻 完 整 代 码
代码示例
js
const map = new maplibregl.Map({
container: 'map',
style: 'https://tiles.openfreemap.org/styles/bright',
zoom: 2
});
map.on('load', () => {
window.setInterval(() => {
// 发送GET请求获取两个随机数0到1之间的数字,用于表示经度和纬度
fetch('https://www.random.org/decimal-fractions/?num=2&dec=10&col=1&format=plain&rnd=new')
.then(r => r.text())
.then(text => {
// 将两个随机数0到1之间的数字转换为度数
const coordinates = text.split('\n').map(l => (Number(l) * 180) - 90);
const json = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates
}
};
// 更新地图上的无人机符号位置为新坐标
map.getSource('drone').setData(json);
// 飞行到无人机当前位置,速度为0.5秒
map.flyTo({
center: json.geometry.coordinates,
speed: 0.5
});
});
}, 2000);
// 设置初始位置为(0,0)
map.addSource('drone', {type: 'geojson', data: {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [0, 0]
}
}});
map.addLayer({
'id': 'drone',
'type': 'symbol',
'source': 'drone',
'layout': {
'icon-image': 'airport'
}
});
});
代码示例
html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Add live realtime data</title>
<meta property="og:description" content="使用实时 GeoJSON 数据流在地图上移动符号。" />
<meta property="og:created" content="2025-06-25" />
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.css' />
<script src='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.js'></script>
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://tiles.openfreemap.org/styles/bright',
zoom: 2
});
map.on('load', () => {
window.setInterval(() => {
// 发起GET请求获取两个随机数
fetch('https://www.random.org/decimal-fractions/?num=2&dec=10&col=1&format=plain&rnd=new')
.then(r => r.text())
.then(text => {
// 将0到1之间的两个随机数转换为度数
const coordinates = text.split('\n').map(l => (Number(l) * 180) - 90);
const json = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates
}
};
// 更新地图上无人机符号的位置
map.getSource('drone').setData(json);
// 让地图飞行到无人机的当前位置
map.flyTo({
center: json.geometry.coordinates,
speed: 0.5
});
});
}, 2000);
// 设置初始位置为(0,0)。
map.addSource('drone', {type: 'geojson', data: {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [0, 0]
}
}});
map.addLayer({
'id': 'drone',
'type': 'symbol',
'source': 'drone',
'layout': {
'icon-image': 'airport'
}
});
});
</script>
</body>
</html>
🔍 代码解析
初始化地图
使用 new maplibregl.Map() 创建地图实例,配置基本参数。本示例的核心特色是实现实时数据更新,通过 setInterval 定时获取数据并更新地图上的符号位置。
javascript
const map = new maplibregl.Map({
container: 'map',
style: 'https://tiles.openfreemap.org/styles/bright',
zoom: 2
});
关键配置项
- container: 地图容器的 DOM 元素 ID
- style : 使用 OpenStreetMap 风格的样式
https://tiles.openfreemap.org/styles/bright - zoom: 初始缩放级别为 2,显示较大地理范围(适合全球视野)
- setInterval: 每 2000ms(2秒)执行一次数据获取和更新
- fetch : 从
https://www.random.orgAPI 获取随机坐标数据 - map.getSource('drone').setData(): 更新 GeoJSON 数据源,实现实时位置更新
- map.flyTo(): 平滑飞行动画到新位置,提升用户体验
实时数据更新流程
- 定时触发 : 使用
setInterval每 2 秒触发一次数据获取 - 数据请求 : 通过
fetch请求外部 API 获取两个 0-1 范围的随机数 - 坐标转换: 将 0-1 范围的随机数转换为经纬度坐标(经度: -180 到 180,纬度: -90 到 90)
- 构造数据: 创建 GeoJSON Feature 对象,包含点几何坐标
- 更新数据源 : 使用
setData()更新地图数据源 - 视图跟随 : 使用
flyTo()让地图平滑移动到无人机新位置
数据源配置
javascript
// 添加 GeoJSON 数据源,初始位置为 [0, 0]
map.addSource('drone', {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [0, 0]
}
}
});
// 添加符号图层,使用机场图标标记无人机位置
map.addLayer({
'id': 'drone',
'type': 'symbol',
'source': 'drone',
'layout': {
'icon-image': 'airport' // 使用内置的机场图标
}
});
⚙️ 参数说明
地图初始化参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| container | string | 是 | - | 地图容器元素的 ID |
| style | string/object | 是 | - | 地图样式 URL 或内联样式对象 |
| zoom | number | 否 | 0 |
初始缩放级别,范围 0-22 |
setInterval 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| callback | function | 是 | 定时执行的回调函数,每次执行时获取数据并更新地图 |
| delay | number | 是 | 执行间隔(毫秒),本示例为 2000(2秒) |
flyTo 配置项
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| center | number, number | 是 | - | 目标中心点坐标,格式为 经度, 纬度 |
| speed | number | 否 | 1.2 |
动画速度,范围 0.1-10,值越小越慢 |
| easing | function | 否 | - | 缓动函数,控制动画节奏 |
| duration | number | 否 | - | 动画持续时间(毫秒),与 speed 互斥 |
setData 方法
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| data | object | 是 | GeoJSON 数据对象,用于更新数据源 |
🎨 效果说明

运行代码后,页面显示一个交互式地图,地图上有一个表示无人机位置的动态符号:
- 实时更新: 每 2 秒自动获取新的随机坐标并更新无人机位置
- 平滑动画 : 使用
flyTo()实现平滑的地图飞行动画,视角跟随无人机移动 - 符号标记 : 使用内置的机场图标(
airport)标记无人机位置,图标清晰可见 - 初始位置 : 无人机从坐标原点
[0, 0](非洲附近)开始 - 全球范围: 随机坐标覆盖全球(经度 -180 到 180,纬度 -90 到 90)
- 交互功能: 支持鼠标拖拽、滚轮缩放、右键旋转等标准地图交互
无人机符号会在全球范围内随机移动,地图会自动平滑跟随无人机位置,呈现出追踪飞行目标的效果。
💡 常 见 问 题
Q1: 实时数据不更新怎么办?
A: 按以下步骤排查:
- 打开浏览器开发者工具(F12),检查 Console 面板是否有报错信息
- 在 Network 面板查看
random.org的请求是否成功返回数据 - 确认 API 地址可正常访问(可直接在浏览器中打开测试)
- 检查
setInterval的时间间隔是否合理设置 - 验证 GeoJSON 数据格式是否正确,确保
coordinates数组有效
Q2: 如何调整更新频率?
A: 修改 setInterval 的第二个参数(毫秒数):
javascript
// 每秒更新一次
window.setInterval(() => { /* ... */ }, 1000);
// 每5秒更新一次
window.setInterval(() => { /* ... */ }, 5000);
Q3: 如何处理数据加载失败?
A: 添加完善的错误处理逻辑:
javascript
fetch(url)
.then(r => {
if (!r.ok) throw new Error('网络请求失败: ' + r.status);
return r.text();
})
.then(text => { /* 处理数据 */ })
.catch(error => {
console.error('加载失败:', error);
// 可选:显示用户友好的错误提示
alert('数据更新失败,请稍后重试');
});
Q4: 实时更新会影响性能吗?
A: 频繁更新可能影响性能。建议:
- 根据实际需求设置合理的更新间隔(一般不小于 1000ms)
- 使用
requestAnimationFrame优化动画渲染 - 在页面卸载或不需要更新时,使用
clearInterval清除定时器 - 避免在回调中执行复杂计算
Q5: 如何暂停和恢复实时更新?
A: 保存定时器 ID,通过 clearInterval 控制:
javascript
let intervalId;
// 开始更新
intervalId = window.setInterval(() => { /* ... */ }, 2000);
// 暂停更新
clearInterval(intervalId);
📝 练习任务
- 基础练习 :修改
setInterval的时间间隔为 5000ms(5秒),观察更新频率变化,并记录每次更新的时间戳 - 进阶挑战:添加一个按钮,点击后暂停/恢复实时更新,并显示当前状态(运行中/已暂停)
- 拓展练习:修改代码,让无人机沿固定路径移动(如正方形、圆形),而不是随机移动
- 拓展思考:如何实现基于真实 GPS 数据的实时追踪功能?需要哪些技术(WebSocket、GPS 设备、数据解析等)?
🌟 最佳实践
- 更新频率: 根据数据特性和用户体验设置合理的更新间隔(一般不小于 1000ms),避免过于频繁的更新导致性能问题
- 错误处理: 添加完善的错误处理机制,处理网络异常、数据格式错误和 API 限流
- 资源清理 : 在页面卸载(
beforeunload)或不需要更新时,使用clearInterval清除定时器,避免内存泄漏 - 动画优化 : 使用
flyTo()或easeTo()实现平滑过渡,设置合适的速度参数提升用户体验 - 数据验证: 在更新地图前验证数据格式,确保 GeoJSON 结构正确
- 防抖节流: 对用户交互事件添加节流,避免在用户操作期间触发更新
- 降级方案: 网络不可用时提供离线数据或友好的提示信息
- 性能监控 : 使用
performanceAPI 监控更新耗时,及时发现性能瓶颈
🔗 延伸阅读
-
下一课预告:将继续学习地图图层的基础知识
本文是MapLibre GL JS实践课程系列的一部分,欢迎关注收藏