You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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>

关键修复点说明:

  1. 增加状态跟踪:用currentSelection变量记录当前要选择的是起点还是终点,解决首次点击只显示起点InfoWindow的问题
  2. 标记事件绑定:每个标记创建时都单独绑定点击事件,确保点击标记能弹出对应地址的自定义InfoWindow
  3. InfoWindow内容动态切换:根据标记类型(起点/终点)动态设置InfoWindow的内容,避免内容固定
  4. 路线绘制后保留标记:在calculateRoute中明确将标记重新添加到地图,防止被DirectionsRenderer影响
  5. 自动切换选择状态:选择完起点后自动切换到终点选择,提升交互体验

替换代码中的YOUR_API_KEY为你的Google Maps API密钥即可测试。

内容的提问来源于stack exchange,提问作者Europeuser

火山引擎 最新活动