API карт Google использует dragend для обновления одного из нескольких маркеров

Я использую API карт Google с несколькими местоположениями оборудования, полученными из базы данных Mysql. Я могу успешно показать маркеры на карте и сделать их перетаскиваемыми. Если я перетащу любой маркер в новое место, он спросит, хотите ли вы обновить базу данных, и если да, предположительно отправляет обновленную широту / долготу в базу данных. Это работает неправильно, и вместо этого всегда обновляется только последний элемент в массиве маркеров.

Обратите внимание, что я успешно сделал это с одним маркером и могу обновить его в любом месте, где перетаскиваю новый маркер. Но для нескольких маркеров я просто не могу получить идентификатор текущего перетаскиваемого маркера и новые данные широты/долготы для отправки обратно на вызов ajax для обновления базы данных для этого конкретного маркера. Я думаю, это потому, что я не получаю доступ к текущим данным маркера, но я борюсь с тем, как это получить.

Любые идеи, что я делаю неправильно? Я знаю, что это должно быть что-то простое, что я не замечаю.

Вот рабочий пример, чтобы продемонстрировать мою проблему: 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.info(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.info(mytitle, mLatLang);
        },
        error: function(xhr, ajaxOptions, thrownError) {
          alert("Error! Update Failed!")
          console.info(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>

JSFiddle не работает из-за ожидаемой проблемы с доменом/API-ключом.

David 17.05.2022 08:42

вы написали "Маркер" в верхнем регистре, должно быть, наверное, в нижнем: function update_marker(Marker, mytitle)

David 17.05.2022 08:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
29
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я внес несколько изменений в ваш код - похоже, он работает нормально, поскольку он отправляет правильные данные через вызов ajax, поэтому с этого момента обновление базы данных должно быть тривиальным.

С помощью тега script, который загружает API Google Maps, вы указываете функцию 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.info('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.info( '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>

Другие вопросы по теме