Google 地图 API 使用 dragend 更新多个标记之一

Google maps API use dragend to update one of multiple markers

我正在使用 google 地图 API 以及从 Mysql 数据库提供的多个设备位置。我可以成功地在地图上显示标记并使它们可拖动。如果我将任何标记拖到新位置,它会提示您是否要更新数据库,如果是,则应该将更新后的 lat/lng 发送到数据库。这不能正常工作,而是总是只更新标记数组中的最后一项。

请注意,我已使用单个标记成功完成此操作,并且能够在我拖动新标记的任何位置更新它。但是对于多个标记,我似乎无法获取当前拖动标记的 ID 和新的 lat/lon 数据以发送回 ajax 调用以更新该特定标记的数据库。我想这是因为我没有访问当前标记的数据,但我正在为如何获取它而苦苦挣扎。

知道我做错了什么吗?我知道这一定是我忽略的简单事情。

这里有一个 Fiddle 来演示我的问题:JSFiddle

<!-- php stuff would be up here to get the database and feed the google API.    Instead here I've just created the const markers to show the markers. -->

<html>

  <head>
    <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAgc6RYO3zsMBE6QVKjkTU-UQ3XhpK0s2A&callback=initMap"></script>
  </head>

  <body>
    <div id="mapCanvas"></div>
  </body>

</html>
<style>#mapCanvas {
    width: 100%;
    height: 850px;
  }
  
  </style>

<script>
function initMap() {
  var map;
  var bounds = new google.maps.LatLngBounds();
  var mapOptions = {
    mapTypeId: 'hybrid'
  };


  // Display a map on the web page
  map = new google.maps.Map(document.getElementById("mapCanvas"), mapOptions);
  map.setTilt(100);

  // Multiple markers location, latitude, and longitude
  const mapIcon = "https://maps.google.com/mapfiles/marker_grey.png";
  const markers = [
    ['Pike-1', 35.42526738862006, -81.172076628969, mapIcon, 10819],
    ['Pike-2', 35.425311504805924, -81.17216095766817, mapIcon, 10820],
    ['Pike-3', 35.425171475622824, -81.17188553479076, mapIcon, 10821],
    ['Pike-4', 35.42530668524588, -81.17134696588283, mapIcon, 10822],
    ['Pike-5', 35.42559347700399, -81.17218140606506, mapIcon, 10823],
    ['Pike-5', 35.426094498781885, -81.17195101338058, mapIcon, 26455],
    ['Pike-6', 35.42532308059036, -81.17215505637606, mapIcon, 26456]
  ];


  // Place each marker on the map  
  for (i = 0; i < markers.length; i++) {
    var position = new google.maps.LatLng(markers[i][1], markers[i][2]);
    var eid = markers[i][4];
    bounds.extend(position);
    marker = new google.maps.Marker({
      position: position,
      map: map,
      draggable: true,
      animation: google.maps.Animation.DROP,
      icon: markers[i][3],
      equipid: markers[i][4],
      title: markers[i][0]
    });



    //Add listener if marker is moved, then ask to update and call function if yes.
    google.maps.event.addListener(marker, 'dragend', function() {
      var mytitle = marker.equipid;
      var latLng = marker.latLng;

      let updateDB = confirm('Update location to database?');
      if (updateDB) {
        update_marker(latLng, mytitle);
        console.log(latLng, mytitle);
      }
    });





    // Center the map to fit all markers on the screen
    map.fitBounds(bounds);

    function update_marker(Marker, mytitle)
    //This is the function that sends the update to the ajax call.  Currently not working.
    //with multiple markers, I can't get the selected marker equipment ID and new lat/lng.
    {
      //Update saved marker from DB and map using jQuery Ajax
      var mLatLang = marker.getPosition().toUrlValue(); //get marker position - this does not get the marker position, but the last row of the result set from mysql
      var mytitle = marker.equipid; //get marker equipment id - this currently gets the last row[id] of the mysql result set.
      var myData = {
        update: 'true',
        name: mytitle,
        latlang: mLatLang
      };
      $.ajax({
        type: "POST",
        url: "equipment-ajaxupdate-gps.php",
        data: myData,
        success: function(data) {
          alert(data);
          console.log(mytitle, mLatLang);
        },
        error: function(xhr, ajaxOptions, thrownError) {
          alert("Error! Update Failed!")
          console.log(mytitle, mLatLang);
        }
      });
    }


  } //end of for( i = 0)

  // Set zoom level
  var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
    this.setZoom(19);
    google.maps.event.removeListener(boundsListener);
  });


} //End of function(initmap)



// Load initialize function
google.maps.event.addDomListener(window, 'load', initMap);


</script>

我对您的代码做了一些更改 - 这似乎工作正常,因为它通过 ajax 调用发送了正确的详细信息,因此从那时起更新数据库应该是微不足道的。

使用加载 Google 地图 api 的脚本标记,您可以指定 callback 函数,因此无需手动调用 initMap 函数google.maps.event.addDomListener(window, 'load', initMap);

update_marker 函数可以简化为使用单个参数,即对标记本身的引用。这极大地简化了标记本身的访问属性,如下所示,函数中使用了 self(可以是任何名称 - 它是对标记的引用)

与使用笨重的 for (i = 0; i < markers.length; i++) { 循环遍历数组元素相比,更简单的 forEach 循环意味着您不再需要使用 name[i][2] 类型语法——尽管如果实际数据来自您的数据库,您可能会使用 JSON 无论如何,这将需要不同的循环策略。

<?php
    if( $_SERVER['REQUEST_METHOD']=='POST' && isset(
        $_POST['update'],
        $_POST['name'],
        $_POST['latlang']
    )){
        
        $_POST['date']=date( DATE_RSS );
        $payload=json_encode( $_POST );
        
        
        exit( $payload );
    }
?>
<html>
    <head>
        <style>
            #mapCanvas {
                width: 100%;
                height: 850px;
            }
        </style>
        <script src='//code.jquery.com/jquery-latest.js'></script>
    </head>
    <body>
        <div id="mapCanvas"></div>
        <script>
            function initMap() {
                var map;
                var bounds = new google.maps.LatLngBounds();
                var mapOptions = {
                    mapTypeId:'hybrid'
                };
                map = new google.maps.Map( document.getElementById("mapCanvas"), mapOptions );
                map.setTilt(100);


                const mapIcon = "https://maps.google.com/mapfiles/marker_grey.png";
                const markers = [
                    ['Pike-1', 35.42526738862006, -81.172076628969, mapIcon, 10819],
                    ['Pike-2', 35.425311504805924, -81.17216095766817, mapIcon, 10820],
                    ['Pike-3', 35.425171475622824, -81.17188553479076, mapIcon, 10821],
                    ['Pike-4', 35.42530668524588, -81.17134696588283, mapIcon, 10822],
                    ['Pike-5', 35.42559347700399, -81.17218140606506, mapIcon, 10823],
                    ['Pike-6', 35.426094498781885, -81.17195101338058, mapIcon, 26455],
                    ['Pike-7', 35.42532308059036, -81.17215505637606, mapIcon, 26456]
                ];


                // Place each marker on the map. 
                // A forEach loop is, IMO, cleaner than the for(i=0;i<n;i++) {} etc
                markers.forEach(a=>{
                    let title=a[0];
                    let latlng=new google.maps.LatLng( a[1], a[2] );
                    let icon=a[3];
                    let eid=a[4];
                    
                    let marker=new google.maps.Marker({
                        position: latlng,
                        map: map,
                        draggable: true,
                        animation: google.maps.Animation.DROP,
                        icon:icon,
                        /* custom properties */
                        equipid:eid,
                        title:title             
                    });
                    bounds.extend( latlng );
                    
                    google.maps.event.addListener( marker, 'dragend', function(e) {
                        if( confirm('Update location to database?') ) {
                            /*
                                Within the context of this function `this` refers
                                to the marker itself that invoked the event handler.
                                
                                Passing `this` as the function parameter to `update_marker`
                                allows us to access all properties of the marker from
                                within that function.
                                
                                As the marker has been assigned custom properties when it was
                                added to the map we can access those easily within `update_marker`
                                
                            */
                            update_marker( this );
                            console.log('Update - Position:%s, Title:%s', this.getPosition().toUrlValue(), this.title );
                        }
                    });
                    
                    function update_marker( self ){
                        /*
                            self is the marker reference
                        */
                        $.ajax({
                            type:"POST",
                            url:location.href,  //"equipment-ajaxupdate-gps.php"
                            data: {
                                update:'true',
                                name:self.title,
                                latlang:self.getPosition().toUrlValue()
                            },
                            success: function( response ) {
                                console.log( 'Ajax response: %o',response );
                                bounds.extend( latlng );
                                map.fitBounds( bounds );
                            },
                            error: function( error ) {
                                alert( "Error! Update Failed!\n"+error )
                            }
                        });
                    };
                    
                });//end forEach loop
                
                map.fitBounds( bounds );
            }
        </script>
        <script async defer src="https://maps.googleapis.com/maps/api/js?key=APIKEY&callback=initMap"></script>
    </body>
</html>