Google Maps Directions Service自定义InfoWindow异常修复求助
修复Google Maps Directions Service自定义InfoWindow异常问题
我仔细排查了你的问题,结合Google Maps API的常见使用坑点,这个InfoWindow的异常主要是状态管理混乱和标记事件绑定时机错误导致的:
- 首次点击地图时,没有区分当前要选择的是起点还是终点,导致只弹出了起点的InfoWindow
- 绘制路线后,标记的点击事件没有正确绑定,或者被DirectionsRenderer的交互覆盖
- InfoWindow实例没有和对应标记关联,导致点击标记时无法触发自定义内容
下面是修复后的完整Demo代码,我已经调整了核心逻辑:
<!DOCTYPE html> <html> <head> <title>Google Maps Directions with Custom InfoWindow</title> <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"></script> <style> #map { height: 400px; width: 100%; } .input-group { margin: 10px 0; display: flex; gap: 8px; } input { padding: 6px; flex: 1; } button { padding: 6px 12px; cursor: pointer; } </style> </head> <body> <div class="input-group"> <input type="text" id="from" placeholder="From Address"> <input type="text" id="to" placeholder="To Address"> <button onclick="calculateRoute()">Get Directions</button> </div> <div id="map"></div> <script> let map; let directionsService; let directionsRenderer; let fromMarker, toMarker; let infoWindow; // 跟踪当前选择状态:'from' 或 'to' let currentSelection = 'from'; function initMap() { map = new google.maps.Map(document.getElementById('map'), { center: { lat: 40.7128, lng: -74.0060 }, // 默认纽约 zoom: 12 }); directionsService = new google.maps.DirectionsService(); directionsRenderer = new google.maps.DirectionsRenderer({ map: map }); infoWindow = new google.maps.InfoWindow(); // 自动补全初始化 const fromInput = document.getElementById('from'); const toInput = document.getElementById('to'); const fromAutocomplete = new google.maps.places.Autocomplete(fromInput); const toAutocomplete = new google.maps.places.Autocomplete(toInput); // 绑定自动补全选择事件 fromAutocomplete.addListener('place_changed', () => handlePlaceSelection('from')); toAutocomplete.addListener('place_changed', () => handlePlaceSelection('to')); // 地图点击事件:选择起点/终点 map.addListener('click', (e) => { const latLng = e.latLng; // 反向地理编码获取地址 const geocoder = new google.maps.Geocoder(); geocoder.geocode({ location: latLng }, (results, status) => { if (status === 'OK' && results[0]) { const address = results[0].formatted_address; if (currentSelection === 'from') { updateMarker('from', latLng, address); document.getElementById('from').value = address; // 切换到终点选择状态 currentSelection = 'to'; } else { updateMarker('to', latLng, address); document.getElementById('to').value = address; // 自动计算路线(可选) calculateRoute(); // 重置选择状态为起点,方便下次选择 currentSelection = 'from'; } } }); }); } // 处理自动补全选择的地点 function handlePlaceSelection(type) { const input = type === 'from' ? document.getElementById('from') : document.getElementById('to'); const place = input.getPlace(); if (!place.geometry || !place.geometry.location) return; updateMarker(type, place.geometry.location, place.formatted_address); // 如果是终点选择完成,自动计算路线 if (type === 'to') calculateRoute(); } // 更新标记并绑定自定义InfoWindow function updateMarker(type, latLng, address) { const oldMarker = type === 'from' ? fromMarker : toMarker; // 移除旧标记 if (oldMarker) oldMarker.setMap(null); // 创建新标记 const newMarker = new google.maps.Marker({ position: latLng, map: map, title: type === 'from' ? 'Start Point' : 'End Point' }); // 绑定标记点击事件:显示自定义InfoWindow newMarker.addListener('click', () => { infoWindow.setContent(`<div><strong>${type === 'from' ? 'From Address' : 'To Address'}</strong><br>${address}</div>`); infoWindow.open(map, newMarker); }); // 保存标记实例 if (type === 'from') { fromMarker = newMarker; // 首次创建起点标记时自动打开InfoWindow infoWindow.setContent(`<div><strong>From Address</strong><br>${address}</div>`); infoWindow.open(map, fromMarker); } else { toMarker = newMarker; // 创建终点标记时自动打开InfoWindow infoWindow.setContent(`<div><strong>To Address</strong><br>${address}</div>`); infoWindow.open(map, toMarker); } // 地图中心移动到标记位置 map.panTo(latLng); } // 计算并绘制路线 function calculateRoute() { const from = document.getElementById('from').value; const to = document.getElementById('to').value; if (!from || !to) { alert('Please fill both from and to addresses'); return; } directionsService.route({ origin: from, destination: to, travelMode: 'DRIVING' }, (response, status) => { if (status === 'OK') { directionsRenderer.setDirections(response); // 确保标记仍然在地图上(DirectionsRenderer不会覆盖标记,但显式设置更稳妥) if (fromMarker) fromMarker.setMap(map); if (toMarker) toMarker.setMap(map); } else { alert('Could not retrieve directions: ' + status); } }); } // 初始化地图 window.onload = initMap; </script> </body> </html>
关键修复点说明:
- 增加状态跟踪:用
currentSelection变量记录当前要选择的是起点还是终点,解决首次点击只显示起点InfoWindow的问题 - 标记事件绑定:每个标记创建时都单独绑定点击事件,确保点击标记能弹出对应地址的自定义InfoWindow
- InfoWindow内容动态切换:根据标记类型(起点/终点)动态设置InfoWindow的内容,避免内容固定
- 路线绘制后保留标记:在
calculateRoute中明确将标记重新添加到地图,防止被DirectionsRenderer影响 - 自动切换选择状态:选择完起点后自动切换到终点选择,提升交互体验
替换代码中的YOUR_API_KEY为你的Google Maps API密钥即可测试。
内容的提问来源于stack exchange,提问作者Europeuser




