如何通过Ajax请求实现地图局部定时刷新(避免整页重载)
解决Ajax定时刷新地图而非整页的问题
看起来你已经找对了方向,但代码里几个小问题导致load()没生效,而且定时刷新的逻辑也没真正触发地图重绘。我帮你梳理下问题点,再给出修正后的代码:
现有代码的核心问题
- setInterval的调用方式错误:用字符串
"my_function();"会导致函数在全局作用域执行,而你的my_function定义在Ajax回调内部,全局访问不到 - load()只更新了时间,没刷新司机数据:你当前的
load()只是重新加载页面里的#time元素,但并没有重新获取最新的司机位置数据,也没重绘地图标记 - 地图重绘逻辑只执行一次:你把地图初始化和标记绘制的代码放在了第一次Ajax成功的回调里,后续定时任务没有执行这些逻辑
- 变量作用域问题:
locationData、locationData2、gmarkers这些变量如果是局部变量,定时任务里会访问不到
修正后的完整实现方案
1. 保持HTML结构不变
<div class="row"> <div class="col-md-12"> <div id="map" style="height: 550px;"> <div id="time"> <?php echo date('H:i:s');?> </div> </div> </div> </div>
2. 重构JavaScript逻辑
// 全局变量,确保定时任务能访问到 let map; let gmarkers = []; let infowindow; let currentStatus = ''; // 初始化地图(只执行一次) function initMap() { map = new google.maps.Map(document.getElementById('map'), { zoom: 10, center: {lat: 31.5204, lng: 74.3587}, mapTypeId: 'roadmap' }); infowindow = new google.maps.InfoWindow({}); } // 获取司机数据并重绘地图 function refreshDrivers() { if (!currentStatus) return; // 如果没有选中状态,不执行 $.ajax({ url: '{{ URL::to('/get_drivers/')}}' + '/' + currentStatus, type: 'get', dataType: 'json', success: function (response) { // 先清除所有旧标记 if (gmarkers.length > 0) { gmarkers.forEach(marker => marker.setMap(null)); gmarkers = []; } // 更新时间显示 $('#time').text(new Date().toLocaleTimeString()); // 假设response返回的是司机位置数据数组,对应你原来的locationData2 const locationData2 = response; for (let i = 0; i < locationData2.length; i++) { const driver = locationData2[i]; // 根据状态设置图标(这里用你原来的逻辑,状态8用灰色车) const icon = currentStatus == 8 ? '{{asset('images/grey-car.png')}}' : '{{asset('images/red-car.png')}}'; const marker = new google.maps.Marker({ position: new google.maps.LatLng(driver.driver_lat, driver.driver_long), map: map, optimized: false, icon: icon }); // 鼠标悬停事件 google.maps.event.addListener(marker, 'mouseover', (function(marker, driver) { return function() { infowindow.setContent(`<h6><b>${driver.first_name}</b></h6>`); infowindow.open(map, marker); } })(marker, driver)); // 点击地图关闭信息窗 google.maps.event.addListener(map, 'click', function() { infowindow.close(); }); gmarkers.push(marker); } // 添加markerLayer用于CSS(如果需要的话) const myoverlay = new google.maps.OverlayView(); myoverlay.draw = function () { this.getPanes().markerLayer.id = 'markerLayer'; }; myoverlay.setMap(map); } }); } // 页面加载完成后初始化地图 $(document).ready(function() { initMap(); // 状态切换事件 $('#status').change(function () { currentStatus = $(this).val(); // 先执行一次刷新 refreshDrivers(); // 清除之前的定时任务(避免重复创建) if (window.refreshInterval) { clearInterval(window.refreshInterval); } // 只有选中"可用"状态(假设状态值是你需要的,比如8?根据你的业务调整)时启动定时刷新 if (currentStatus === '8') { // 这里替换成你实际的"可用"状态值 window.refreshInterval = setInterval(refreshDrivers, 10000); // 每10秒执行一次 } }); });
关键改动说明
- 地图初始化分离:
initMap()只在页面加载时执行一次,避免重复创建地图实例 - 封装刷新逻辑:把获取数据、清除旧标记、绘制新标记的逻辑放在
refreshDrivers()里,方便调用 - 修正定时任务:用函数引用
refreshDrivers代替字符串调用,避免作用域问题;同时切换状态时先清除旧的定时任务,防止多个定时器同时运行 - 状态存储:用
currentStatus全局变量存储当前选中的状态,定时任务可以直接使用 - 直接更新时间:不需要用
load()加载整个页面的#time,直接用text()更新当前时间更高效 - 简化事件绑定:优化了信息窗的事件绑定逻辑,避免闭包问题
这样修改后,当你切换到"可用"状态时,会立即刷新一次地图,之后每10秒自动获取最新的司机数据并重绘地图,不会触发整页重载。
内容的提问来源于stack exchange,提问作者user10748394
相关产品推荐
相关产品推荐

