简体   繁体   English

使用 event.trigger 将标记和折线添加到谷歌地图以模拟点击与实际点击不同

[英]Adding markers and polyline to a google map with a event.trigger to mimic a click works different than an actual click

I am trying to update a google map with google.maps.DirectionsService and google.maps.Polyline.我正在尝试使用 google.maps.DirectionsService 和 google.maps.Polyline 更新谷歌地图。 The map may be empty on initiation, or start with coordinates from an array.地图在启动时可能是空的,或者以数组中的坐标开始。

When the map is empty, each location the user click will become a marker, and there will be a polyline path drawn between the markers, and the path will be adjusted as a user deletes markers.当地图为空时,用户点击的每个位置都会成为一个标记,标记之间会绘制一条折线路径,路径会随着用户删除标记而调整。

It all works well when using the click event handler on a manual mouse click.在手动单击鼠标时使用单击事件处理程序时一切正常。

The problem is when I try to populate the map with markers created by coordinates from the array.问题是当我尝试使用由数组中的坐标创建的标记填充地图时。 I am trying to simply put the marker latlng coordinates in with an array and iterate through the array doing the same thing as if someone was clicking the map.我试图简单地将标记 latlng 坐标放入一个数组中,然后遍历该数组,就像有人单击地图一样执行相同的操作。

I tried it both iterating through the array with the same code as clicking, as well as even iterating through the array to mimic a click event, calling the same function as if clicking on the map.我尝试过使用与单击相同的代码遍历数组,甚至遍历数组以模拟单击事件,调用与单击地图相同的函数。

For some reason, when I do it manually clicking, the code runs like I expect.出于某种原因,当我手动单击时,代码会按我预期的方式运行。 When I run it iterating through the array, the order of the code is somehow messed up and the markers show up, but the polyline path is drawing too many lines, connecting too many points.当我运行它遍历数组时,代码的顺序不知何故被打乱了,标记出现了,但是多段线路径绘制了太多的线,连接了太多的点。

I am new to JavaScript other than very simple DOM manipulation so I suspect it has something to do with the async functions used by the google maps API which I do not fully understand.除了非常简单的 DOM 操作之外,我是 JavaScript 的新手,所以我怀疑它与我不完全理解的 google maps API 使用的异步函数有关。 I tried to use "await" where I could think to.我试着在我能想到的地方使用“等待”。 I am not sure if I am using them correctly, but like I say, it works when I click on the map.我不确定我是否正确使用它们,但就像我说的,当我点击地图时它会起作用。

Thinking that perhaps the array is too fast for the API to keep up, I put in a timer to slow it down between iterations, but it still turns out differently.考虑到数组可能太快以至于 API 无法跟上,我放入了一个计时器以在迭代之间减慢它的速度,但结果仍然不同。

Here is the code.这是代码。

<!DOCTYPE html>
<html>
<head>
  <style>
    #map {height: 600px;width: 100%;}
    .log {margin: 0 0 0 0;padding: 0 0 0 0;}
  </style>
</head>
<body>
  <div id="map"></div>
  <button id="delete-marker">Delete Marker</button>
  <pre id="markersAndPaths"></pre>
  <div id="log"></div>
  <script>

    let map;
    let polyline;
    let directionsService;
    let markers = [];
    let sections = [];
    let fullPath = []; 
    var start = new Date().getTime();
    let default_markers = [
        [36.92137740132106, 138.44167498874666],
        [36.9201679950352, 138.44216315078737],
        [36.92008222081132, 138.43934683132173],
    ]
    function initMap() {
        mapOptions = {
            center: { lat: 36.921, lng: 138.443 },
            zoom: 17,
            scrollwheel: true,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        map = new google.maps.Map(document.getElementById('map'), mapOptions);

        directionsService = new google.maps.DirectionsService();
        polyline = new google.maps.Polyline();
        let debug;
        //debug = 1000;
    if (debug > 0) {
        
        for (var i = 0; i < default_markers.length; i++) {
            var position = new google.maps.LatLng(default_markers[i][0], default_markers[i][1]);
            var marker = new google.maps.Marker({
                 position: position,
                 map: map
            });
            map.setCenter(marker.getPosition());
            map.panTo(map.getCenter());
            markers.push(marker);
            marker.id = markers.length
            
            if (markers.length > 1) {
                doclog(`call polyline m${markers.length}: s${sections.length}`)
                updatePolyLine();
                doclog(``, 'hr')
            }
        }
    }

        map.addListener('click', function(event) {
            var marker = new google.maps.Marker({
                position: event.latLng,
                map: map
            });
            doclog(`markers.length: ${markers.length} event.latlng:${event.latLng}`)
            map.setCenter(marker.getPosition());
            map.panTo(map.getCenter());
            markers.push(marker);
            marker.id = markers.length
            if (markers.length > 1) {
                doclog(`call polyline  m${markers.length}: s${sections.length}`)
                updatePolyLine();
                doclog(``, 'hr')
            }
        });
        
        for (var x = 0; x < default_markers.length; x++) {
            const latLng = new google.maps.LatLng(default_markers[x][0], default_markers[x][1]);
            google.maps.event.trigger(map, 'click', {latLng: latLng});
            //while (new Date().getTime() < start + 1000);  
        }

        document.getElementById('delete-marker').addEventListener('click', function(event) {
            var undone = markers.pop();
            if (markers.length > 0) {
                map.setCenter(markers[markers.length-1].getPosition());
                map.panTo(map.getCenter());
            }
            sections.pop();
            sections.pop();
            undone.setMap(null);
            if (markers.length > 0) {
                updatePolyLine();
            }
        });
    }

    async function updatePolyLine() {
        fullPath = [];
        doclog(`Insdie updatePolyLine: Markers: ${markers.length}`)
        for (var i = 1; i < markers.length; i++) {
            doclog(`${i} < ${markers.length} (i < maerkers.length)`)
            console.log(`${i} < ${markers.length}`);
            if (i == markers.length - 1) {

                doclog(`${i} == ${markers.length - 1} (i == markers.length - 1)`)
                var start = markers[i-1].getPosition()
                var end = markers[i].getPosition()
                var section_id = `${markers[i-1].id}-${markers[i].id}`;
                let section = {
                        'id': section_id,
                        'start_id': markers[i-1].id,
                        'start': start,
                        'end_id': markers[i].id,
                        'end': end,
                        'waypoints': []
                    }
                sections.push(section);
                doclog(`sections.push(${section.id}); sections.length ${sections.length} (i == markers.length - 1)`)
             }  
        }

        for (var i = 0; i < (sections.length); i++) {
            doclog(` .   Inside sections loop: ${i} < ${sections.length}: (i < (sections.length))`)
            doclog(`id = ${sections[i].id} of ${sections.length}`)
            if (sections[i].waypoints == '') {
                await getRoute(sections[i], sections[i].start, sections[i].end)
            } 
            doclog(` .   ----- push to fullpath ------`)
            fullPath.push(sections[i].waypoints);
        }
                
        polyline.setPath(fullPath.flat());
        polyline.setMap(map)

        logMarkersAndSections()
        
        function updateSection(response, section) {
            var path = []
            for (var i = 0, len = response.routes[0].overview_path.length; i < len; i++) {
                path.push(response.routes[0].overview_path[i]);
                console.log(`start_id ${section.start_id} ${response.routes[0].overview_path[i]}`)
            }
            section.waypoints = path;
        }

        async function getRoute(section, start, end) {
            doclog(`Call getRoute sections[${i}](${sections[i]}, ${sections[i].start},${sections[i].end})`)
            var routeOptions = {
                    origin: section.start,
                    destination: section.end,
                    travelMode: 'DRIVING'
            }
            await directionsService.route(routeOptions)
                .then(async function(response) {
                   await updateSection(response, section);
            });   
            doclog(`GOT Route sections[${i}](${sections[i]}, ${sections[i].start},${sections[i].end})`)
                
        };  
    };

    window.initMap = initMap;
  </script>




<script>

    function doclog(data, tag) {
        var stack = new Error().stack;
        var lines = stack.split('\n');
        var lineNumber = lines[2].match(/(\d+):(\d+)/);;
        tag ||= 'p';
        var div = document.getElementById("log");
        var element = document.createElement(tag);
        element.classList.add("log");
        element.innerHTML = (`[${lineNumber[0]}] ${data}`);
        div.appendChild(element);
    }

    function logFullPath() {
        out = `${fullPath}`
        document.getElementById("fullPath").innerHTML = out.replace(/,\(/g, ",\n(");
    }

    function logMarkersAndSections() {
        out = `markers<br>`;
        for (var i = 0; i < markers.length; i++) {
            out += `[${i}] : ${markers[i].position}<br>`
        }
        out += `Sections<br>`;
        for (var i = 0; i < sections.length; i++) {
            out += `[${i}] : (${sections[i].id}) : ${sections[i].start} -> ${sections[i].end}<br>`
        }
        document.getElementById("markersAndPaths").innerHTML = out;
    }

  </script>

<script async defer
src="https://maps.googleapis.com/maps/api/js?key=[apikey]&callback=initMap">
</script>
</body>
</html>

Here is some of the logging I got the first one is when I click three points on the map manually using the click event by clicking with a mouse:这是我得到的一些日志记录,第一个是当我通过单击鼠标使用单击事件手动单击地图上的三个点时:

markers
[0] : (36.921849150345615, 138.442817609787)
[1] : (36.92006506595496, 138.4419914894104)
[2] : (36.919876362280334, 138.44024805355073)
Sections
[0] : (1-2) : (36.921849150345615, 138.442817609787) -> (36.92006506595496, 138.4419914894104)
[1] : (2-3) : (36.92006506595496, 138.4419914894104) -> (36.919876362280334, 138.44024805355073)
[67:13] markers.length: 0 event.latlng:(36.921849150345615, 138.442817609787)
[67:13] markers.length: 1 event.latlng:(36.92006506595496, 138.4419914894104)
[76:17] call polyline m2: s0
[105:9] Insdie updatePolyLine: Markers: 2
[107:13] 1 < 2 (i < maerkers.length)
[111:17] 1 == 1 (i == markers.length - 1)
[124:17] sections.push(1-2); sections.length 1 (i == markers.length - 1)
[129:13] . Inside sections loop: 0 < 1: (i < (sections.length))
[130:13] id = 1-2 of 1
[154:13] Call getRoute sections[0]([object Object], (36.921849150345615, 138.442817609787),(36.92006506595496, 138.4419914894104))
[78:17
[164:13] GOT Route sections[0]([object Object], (36.921849150345615, 138.442817609787),(36.92006506595496, 138.4419914894104))
[134:13] . ----- push to fullpath ------
[67:13] markers.length: 2 event.latlng:(36.919876362280334, 138.44024805355073)
[76:17] call polyline m3: s1
[105:9] Insdie updatePolyLine: Markers: 3
[107:13] 1 < 3 (i < maerkers.length)
[107:13] 2 < 3 (i < maerkers.length)
[111:17] 2 == 2 (i == markers.length - 1)
[124:17] sections.push(2-3); sections.length 2 (i == markers.length - 1)
[129:13] . Inside sections loop: 0 < 2: (i < (sections.length))
[130:13] id = 1-2 of 2
[134:13] . ----- push to fullpath ------
[129:13] . Inside sections loop: 1 < 2: (i < (sections.length))
[130:13] id = 2-3 of 2
[154:13] Call getRoute sections[1]([object Object], (36.92006506595496, 138.4419914894104),(36.919876362280334, 138.44024805355073))
[78:17]
[164:13] GOT Route sections[1]([object Object], (36.92006506595496, 138.4419914894104),(36.919876362280334, 138.44024805355073))
[134:13] . ----- push to fullpath ------

The second one is when I iterate through the default_array to call google.maps.event.trigger(map, 'click', {latLng: latLng});第二个是当我遍历 default_array 调用 google.maps.event.trigger(map, 'click', {latLng: latLng});

Everything is the same up until it gets to where the manually clicked markers retrieves a Route Section and pushes it into the fullpath[].一切都是一样的,直到它到达手动单击的标记检索路线部分并将其推入完整路径 [] 的位置。 The iterated markers skips that and calls the updatePolyLine() function.迭代标记会跳过它并调用 updatePolyLine() 函数。

markers
[0] : (36.92137740132106, 138.44167498874666)
[1] : (36.9201679950352, 138.44216315078737)
[2] : (36.92008222081132, 138.43934683132173)
Sections
[0] : (1-2) : (36.92137740132106, 138.44167498874666) -> (36.9201679950352, 138.44216315078737)
[1] : (2-3) : (36.9201679950352, 138.44216315078737) -> (36.92008222081132, 138.43934683132173)
[67:13] markers.length: 0 event.latlng:(36.92137740132106, 138.44167498874666)
[67:13] markers.length: 1 event.latlng:(36.9201679950352, 138.44216315078737)
[76:17] call polyline m2: s0
[105:9] Insdie updatePolyLine: Markers: 2
[107:13] 1 < 2 (i < maerkers.length)
[111:17] 1 == 1 (i == markers.length - 1)
[124:17] sections.push(1-2); sections.length 1 (i == markers.length - 1)
[129:13] . Inside sections loop: 0 < 1: (i < (sections.length))
[130:13] id = 1-2 of 1
[154:13] Call getRoute sections[0]([object Object], (36.92137740132106, 138.44167498874666),(36.9201679950352, 138.44216315078737))
[78:17
[67:13] markers.length: 2 event.latlng:(36.92008222081132, 138.43934683132173)
[76:17] call polyline m3: s1
[105:9] Insdie updatePolyLine: Markers: 3
[107:13] 1 < 3 (i < maerkers.length)
[107:13] 2 < 3 (i < maerkers.length)
[111:17] 2 == 2 (i == markers.length - 1)
[124:17] sections.push(2-3); sections.length 2 (i == markers.length - 1)
[129:13] . Inside sections loop: 0 < 2: (i < (sections.length))
[130:13] id = 1-2 of 2
[154:13] Call getRoute sections[0]([object Object], (36.92137740132106, 138.44167498874666),(36.9201679950352, 138.44216315078737))
[78:17]
[164:13] GOT Route sections[0]([object Object], (36.92137740132106, 138.44167498874666),(36.9201679950352, 138.44216315078737))
[134:13] . ----- push to fullpath ------
[129:13] . Inside sections loop: 1 < 2: (i < (sections.length))
[130:13] id = 2-3 of 2
[154:13] Call getRoute sections[1]([object Object], (36.9201679950352, 138.44216315078737),(36.92008222081132, 138.43934683132173))
[164:13] GOT Route sections[0]([object Object], (36.92137740132106, 138.44167498874666),(36.9201679950352, 138.44216315078737))
[134:13] . ----- push to fullpath ------
[129:13] . Inside sections loop: 1 < 2: (i < (sections.length))
[130:13] id = 2-3 of 2
[154:13] Call getRoute sections[1]([object Object], (36.9201679950352, 138.44216315078737),(36.92008222081132, 138.43934683132173))
[164:13] GOT Route sections[1]([object Object], (36.9201679950352, 138.44216315078737),(36.92008222081132, 138.43934683132173))
[134:13] . ----- push to fullpath ------
[164:13] GOT Route sections[1]([object Object], (36.9201679950352, 138.44216315078737),(36.92008222081132, 138.43934683132173))
[134:13] . ----- push to fullpath ------

Give the browser time to request, receive and render the directions segments after triggering the "click" event on the map:在触发地图上的“点击”事件后,让浏览器有时间请求、接收和呈现路线段:

for (var x = 0; x < default_markers.length; x++) {
    const latLng = new google.maps.LatLng(default_markers[x][0], default_markers[x][1]);
    setTimeout(function() {
        google.maps.event.trigger(map, 'click', {latLng: latLng});
    },1000*x);  // 1 second between clicks
}

proof of concept fiddle概念证明小提琴

结果地图的屏幕截图

code snippet:代码片段:

 let map; let polyline; let directionsService; let markers = []; let sections = []; let fullPath = []; var start = new Date().getTime(); let default_markers = [ [36.92137740132106, 138.44167498874666], [36.9201679950352, 138.44216315078737], [36.92008222081132, 138.43934683132173], ] function initMap() { mapOptions = { center: { lat: 36.921, lng: 138.443 }, zoom: 17, scrollwheel: true, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById('map'), mapOptions); directionsService = new google.maps.DirectionsService(); polyline = new google.maps.Polyline(); map.addListener('click', function(event) { var marker = new google.maps.Marker({ position: event.latLng, map: map }); map.setCenter(marker.getPosition()); map.panTo(map.getCenter()); markers.push(marker); marker.id = markers.length if (markers.length > 1) { updatePolyLine(); } }); for (var x = 0; x < default_markers.length; x++) { const latLng = new google.maps.LatLng(default_markers[x][0], default_markers[x][1]); setTimeout(function() { google.maps.event.trigger(map, 'click', { latLng: latLng }); }, 1000 * x); } document.getElementById('delete-marker').addEventListener('click', function(event) { var undone = markers.pop(); if (markers.length > 0) { map.setCenter(markers[markers.length - 1].getPosition()); map.panTo(map.getCenter()); } sections.pop(); sections.pop(); undone.setMap(null); if (markers.length > 0) { updatePolyLine(); } }); } async function updatePolyLine() { fullPath = []; for (var i = 1; i < markers.length; i++) { if (i == markers.length - 1) { var start = markers[i - 1].getPosition() var end = markers[i].getPosition() var section_id = `${markers[i-1].id}-${markers[i].id}`; let section = { 'id': section_id, 'start_id': markers[i - 1].id, 'start': start, 'end_id': markers[i].id, 'end': end, 'waypoints': [] } sections.push(section); } } for (var i = 0; i < (sections.length); i++) { if (sections[i].waypoints == '') { await getRoute(sections[i], sections[i].start, sections[i].end) } fullPath.push(sections[i].waypoints); } polyline.setPath(fullPath.flat()); polyline.setMap(map) function updateSection(response, section) { var path = [] for (var i = 0, len = response.routes[0].overview_path.length; i < len; i++) { path.push(response.routes[0].overview_path[i]); } section.waypoints = path; } async function getRoute(section, start, end) { var routeOptions = { origin: section.start, destination: section.end, travelMode: 'DRIVING' } await directionsService.route(routeOptions).then(async function(response) { await updateSection(response, section); }); }; }; window.initMap = initMap;
 #map { height: 80%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; }
 <:DOCTYPE html> <html> <head> <title>Directions Service</title> <script src="https.//polyfill.io/v3/polyfill.min?js:features=default"></script> <.-- jsFiddle will insert css and js --> </head> <body> <div id="map"></div> <button id="delete-marker">Delete Marker</button> <pre id="markersAndPaths"></pre> <div id="log"></div> <script src="https.//maps?googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&v=weekly" defer></script> </body> </html>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM