本文介绍如何通过定时轮询 json 数据并更新地图标记,实现车辆 gps 位置的实时刷新,重点解决数据未同步更新、旧标记残留等问题。
在基于 Google Maps JavaScript API 构建实时车辆追踪系统时,仅定时拉取新数据(fetchAPI)是不够的——若不将响应结果赋值回全局 data 变量,后续 setMarker() 函数始终渲染的是初始快照,导致地图标记“卡死”在首次加载的位置。
首先,修正 fetchAPI:移除 return,改为直接更新共享变量 data:
let data = null; // 初始化为 null,避免未定义引用
const fetchAPI = async () => {
try {
const response = await fetch('./cradlepoint.json');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const locations = await response.json();
data = locations; // ✅ 关键:实时覆盖 data
} catch (err) {
console.error('Failed to fetch vehicle data:', err);
}
};接着,必须清理旧标记,否则每 5 秒都会叠加新标记,造成内存泄漏与视觉混乱。推荐使用 Marker 实例数组集中管理:
let markers = []; // 存储所有活跃标记的引用 function setMarker() { // ✅ 清除所有现有标记 markers.forEach(marker => marker.setMap(null)); markers = []; // ✅ 确保 data 已就绪且包含有效数据 if (!data || !Array.isArray(data.data) || data.data.length === 0) return; const busicon = "https://maps.google.com/mapfiles/ms/icons/bus.png"; const infoWindow = new google.maps.InfoWindow(); data.data.forEach(vehicle => { const { id, latitude, longitude } = vehicle; // ✅ 创建新标记并保存引用 const marker = new google.maps.Marker({ map, position: { lat: latitude, lng: longitude }, icon: busicon, title: id, }); // ✅ 绑定点击事件(注意:infoWindow 复用,避免重复创建) marker.addListener('click', () => { infoWindow.close(); infoWindow.setContent(`Vehicle ID: ${id}`); infoWindow.open(map, marker); }); markers.push(marker); // 记录引用,便于后续清除 }); }
async function initMap() {
const { Map } = await google.maps.importLibrary("maps");
const { Marker } = await google.maps.importLibrary("marker");
map = new Map(document.getElementById("map"), {
mapId: "YOUR_MAP_ID",
center: { lat: 37.7749, lng: -122.4194 }, // 示例坐标
zoom: 14,
});
// 首次加载数据并渲染
await fetchAPI();
setMarker();
// ✅ 启动轮询:先拉取新数据,再刷新标记
setInterval(async () => {
await fetchAPI(); // 等待数据更新完成
setMarker(); // 再渲染最新状态
}, 5000);
}
// 页面加载完成后初始化
window.addEventListener('load', initMap);通过以上重构,你的地图将真正实现「数据驱动」的动态刷新——每次轮询后,旧标记被精准清除,新位置被实时呈现,为车队监控提供可靠可视化支持。