【问题标题】:Update markers from Ajax Json array in google map when map is moved移动地图时从谷歌地图中的 Ajax Json 数组更新标记
【发布时间】:2018-06-21 15:40:49
【问题描述】:

我希望我的 Google 地图在移动地图时更新标记 - 使用 bounds_changed 或 idle - 通过提交新的 Ajax、删除现有标记并放置新集。

到目前为止,我有以下两个脚本: - 第一个从 JSON 数组中读取标题、纬度和经度,并将标记正确放置在地图中。但我无法正确添加 bounds_changed 代码。 - 第二个脚本包含一个 bounds_changed 触发器,它将一组新的标记加载到一个 div 中,但我不知道如何输入该数组作为标记的数据(并更新它们)。

如果你能帮我修复这两个脚本中的任何一个,以便我可以让这两个工作正常工作 - 从 JSON 数组中读取标记,如脚本 1 中那样,并在地图移动时更新数组,如脚本 2 中那样 - 我将非常感激.

我尝试了许多变体,并阅读了所有与该问题相关的 SO 问题,但没有运气。完全卡住了!

脚本 1 - 从 JSON 数组中获取标记:

<script>
jQuery(function($) {
    // Asynchronously Load the map API
    var script = document.createElement('script');
    script.src = "https://maps.googleapis.com/maps/api/js?key=SECRET&sensor=false&callback=initialize";
    document.body.appendChild(script);
});

function initialize() {
    var map;
    var bounds = new google.maps.LatLngBounds();
    var mapOptions = {
        mapTypeId: 'roadmap'
    };
    ne_lng = -70.18087440625004;
    sw_lng = -92.10958534375004;
    ne_lat = 44.078852008513245;
    sw_lat = 28.9109895909681;

    // Display a map on the page
    map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
    map.setTilt(45);
    var latlngData = 0;

        // Info Window Content
        var infoWindowContent = [
            ['<div class="info_content">' +
            '<h3>London Eye</h3>' +
            '<p>The London Eye is a giant Ferris wheel situated on the banks of the River Thames. The entire structure is 135 metres (443 ft) tall and the wheel has a diameter of 120 metres (394 ft).</p>' + '</div>'],
            ['<div class="info_content">' +
            '<h3>Palace of Westminster</h3>' +
            '<p>The Palace of Westminster is the meeting place of the House of Commons and the House of Lords, the two houses of the Parliament of the United Kingdom. Commonly known as the Houses of Parliament after its tenants.</p>' +
            '</div>']
        ];

        // Display multiple markers on a map, same info for everyone, just an example
        var infoWindow = new google.maps.InfoWindow(), marker, i;

        // Loop through our array of markers & place each one on the map, fetching avg_gps_latitude,   avg_gps_longitude from latlngData, received from ajax call ( but it dodn't work)
        loadLocations().done(function (latlngData) {


            for (i = 0; i < latlngData.length; i++) {
                var position = new google.maps.LatLng(latlngData[i].latitude, latlngData[i].longitude);
                bounds.extend(position);
                marker = new google.maps.Marker({
                    position: position,
                    map: map,
                    title: latlngData[i].ssid
                });

                // Allow each marker to have an info window
                google.maps.event.addListener(marker, 'click', (function (marker, i) {
                    return function () {
                        infoWindow.setContent(infoWindowContent[0][0]);
                        infoWindow.open(map, marker);
                    }
                })(marker, i));

                // Automatically center the map fitting all markers on the screen
                map.fitBounds(bounds);
            }

          });


        // Override our map zoom level once our fitBounds function runs (Make sure it only runs once)
        var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function (event) {
            this.setZoom(6);
            google.maps.event.removeListener(boundsListener);
        });
    }


    function loadLocations()
    {
        return $.ajax({
              type:'POST',
              url: 'includes/newjson.php',
              dataType: 'json',
              data:{
                a: ne_lat,
                b: ne_lng,
                c: sw_lat,
                d: sw_lng
      },
      async: true,
      //cache: false,
      success: function(result){
          console.log("successx");
          console.log(result);
          var jsonStr = JSON.stringify(result);
          $('#results').html(jsonStr);
          // $('#results').html(result);
           // initialize();
          },
        error: function (xhr, ajaxOptions, thrownError) {
          alert(xhr.status);
          alert(thrownError);
        }
  });
  }

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


</script>

脚本 2 - 当地图移动但未传递到 Google 地图标记时,使用 JSON 数组更新 #result 中的数组(原始数组在脚本中作为 PHP 变量输入):

    <script type="text/javascript">
jQuery(function($) {
    // Asynchronously Load the map API
    var script = document.createElement('script');
    script.src = "https://maps.googleapis.com/maps/api/js?key=SECRET&sensor=false&callback=initialize";
    document.body.appendChild(script);
});

function initialize() {
    var map;
    var bounds = new google.maps.LatLngBounds();
    var mapOptions = {
        mapTypeId: 'roadmap'
    };

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

    google.maps.event.addListener(map, 'bounds_changed', function(){
        // alert(this.getBounds());
    ne_lng = map.getBounds().getNorthEast().lng();
    sw_lng = map.getBounds().getSouthWest().lng();
    ne_lat = map.getBounds().getNorthEast().lat();
    sw_lat = map.getBounds().getSouthWest().lat();
    console.log(ne_lng);
    console.log(sw_lng);
    console.log(ne_lat);
    console.log(sw_lat);

    $.ajax({
        type:'POST',
        url: 'includes/mapQuery.php',
        data:{
          a: ne_lat,
          b: ne_lng,
          c: sw_lat,
          d: sw_lng
},
async: true,
cache: false,
        success: function(result){
            console.log("success");
            $('#results').html(result);
            // newmarkers = result;
            // console.log(newmarkers);
        } // End of success function of ajax form
    }); // End of ajax call

    });

    // Multiple Markers
    var markers =
    <?php
        echo str_replace('"', "'", json_encode($maparray, JSON_NUMERIC_CHECK));
    ?>
    ;

    // Info Window Content
    var infoWindowContent = [
        ['<div class="info_content">' +
        '<h3>London Eye</h3>' +
        '<p>The London Eye is a giant Ferris wheel situated on the banks of the River Thames. The entire structure is 135 metres (443 ft) tall and the wheel has a diameter of 120 metres (394 ft).</p>' +        '</div>'],
        ['<div class="info_content">' +
        '<h3>Palace of Westminster</h3>' +
        '<p>The Palace of Westminster is the meeting place of the House of Commons and the House of Lords, the two houses of the Parliament of the United Kingdom. Commonly known as the Houses of Parliament after its tenants.</p>' +
        '</div>']
    ];

    // Display multiple markers on a map
    var infoWindow = new google.maps.InfoWindow(), marker, i;

    // Loop through our array of markers & place each one on the map
    for( i = 0; i < markers.length; i++ ) {
        var position = new google.maps.LatLng(markers[i][1], markers[i][2]);
        bounds.extend(position);
        var iconBase = 'img/icons/';
        marker = new google.maps.Marker({
            position: position,
            map: map,
            icon: iconBase + 'student-icon.png',
            title: markers[i][0]
        });

        // Allow each marker to have an info window
        google.maps.event.addListener(marker, 'click', (function(marker, i) {
            return function() {
                infoWindow.setContent(infoWindowContent[i][0]);
                infoWindow.open(map, marker);
            }
        })(marker, i));

        // Automatically center the map fitting all markers on the screen
        map.fitBounds(bounds);
    }

    // Override our map zoom level once our fitBounds function runs (Make sure it only runs once)
    var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
        this.setZoom(6);
        google.maps.event.removeListener(boundsListener);
    });



}</script>

【问题讨论】:

  • 刚刚收到对这个问题的反对票,这显然表明“没有研究工作”或表述不清的问题。对于第一部分,情况绝对不是这样:我花了两天时间来提出我发布的两个单独的解决方案,并咨询了每一个甚至是切线相关的帖子(以及其他地方)。问题不在于缺乏研究(但可能是我缺乏知识)。至于含糊不清的问题,我选择照原样提出,而不是发布我的许多失败尝试,因为我不相信它们是否走在正确的轨道上。
  • 嗨 mads Stenbjerre,我和你上面提到的问题一样。如果你解决了,你能不能请发布答案。我会感谢你的。谢谢。
  • 嗨 Rax,请参阅下面的最终代码。祝你好运!
  • @MadsStenbjerre 你好,我尝试运行你的代码,因为我想要的和你的完全一样。但是无法实现它可以请检查它吗? stackoverflow.com/questions/54759041/…

标签: javascript json ajax google-maps google-maps-api-3


【解决方案1】:

这是对我有用的解决方案。结果可见here

JSON 数据来自这个 php 文件,该文件会在地图移动时更新:

include("conn.php");
$ne_lat = $_POST['a'];
$ne_lon = $_POST['b'];
$sw_lat = $_POST['c'];
$sw_lon = $_POST['d'];

$result = mysqli_query($con,"SELECT schoolname, latitude, longitude, total_students, act_composite_25, schoolid, (sat_critread_25+sat_math_25) as sat, (100 * admissions_total/applicants_total) as admrate, degree_bachelor, degree_masters, url, city, usstate, tuition_outstate, tuition_instate FROM usschools WHERE
(CASE WHEN $ne_lat < $sw_lat
        THEN latitude BETWEEN $ne_lat AND $sw_lat
        ELSE latitude BETWEEN $sw_lat AND $ne_lat
END)
AND
(CASE WHEN $ne_lon < $sw_lon
        THEN longitude BETWEEN $ne_lon AND $sw_lon
        ELSE longitude BETWEEN $sw_lon AND $ne_lon
END) and degree_bachelor = 1 order by act_composite_25 desc limit 20");
  if (!$result) {
    printf("Error: %s\n", mysqli_error($con));
    exit();
}

while ($row = $result->fetch_assoc()) {
  $data[] = $row;
  }

生成地图并更新标记,如下所示:

    <script>
    jQuery(function($) {
        // Asynchronously Load the map API
        var script = document.createElement('script');
        script.src = "https://maps.googleapis.com/maps/api/js?key=MYKEY&sensor=false&callback=initialize";
        document.body.appendChild(script);
    });

        ne_lng = -70.18087440625004;
        sw_lng = -92.10958534375004;
        ne_lat = 44.078852008513245;
        sw_lat = 28.9109895909681;

        function initialize() {
          var markers;
          var map;
          var markers1 = [];


            var bounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(46.35960484925907, -81.34113061749997),
    new google.maps.LatLng(39.41643540717689, -70.37677514874997)
);
            var mapOptions = {
                mapTypeId: 'roadmap'
            };

        // Display a map on the page
        map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
        map.setTilt(45);
        var latlngData = 0;


        var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function (event) {
            this.setZoom(6);
            google.maps.event.removeListener(boundsListener);
        });
// Automatically center the map fitting all markers on the screen
map.fitBounds(bounds);

// would be great if a margin could be added to prevent schools on edges from loading without marker
google.maps.event.addListener(map, 'idle', function() {
    ne_lng = map.getBounds().getNorthEast().lng()-0.01;
    sw_lng = map.getBounds().getSouthWest().lng()+0.01;
    ne_lat = map.getBounds().getNorthEast().lat()-0.01;
    sw_lat = map.getBounds().getSouthWest().lat()+0.01;
    console.log(ne_lng);
    console.log(sw_lng);
    console.log(ne_lat);
    console.log(sw_lat);

      function loadLocations()
        {
          $("#results").empty();
            return $.ajax({
                  type:'POST',
                  url: 'includes/newjson.php',
                  dataType: 'json',
                  data:{
                    a: ne_lat,
                    b: ne_lng,
                    c: sw_lat,
                    d: sw_lng
          },
          async: true,
          success: function(result){
              console.log("ajax");
              console.log(result);

              var len = result.length;
            for(var i=0; i<len; i++){
                var id = result[i].schoolid;
                var name = result[i].schoolname;
                var students = (result[i].total_students).toLocaleString();
                var act = result[i].act_composite_25;
                var sat = result[i].sat;
                var acceptancerate = (result[i].admrate).toFixed(1);
                var degree_bachelor = result[i].degree_bachelor;
                var degree_masters = result[i].degree_masters;
                var url = result[i].url;
                var city = result[i].city;
                var usstate = result[i].usstate;
                var tuition_outstate = (result[i].tuition_outstate).toLocaleString();
                var tuition_instate = (result[i].tuition_instate).toLocaleString();
                var tr_str = "<div class='resultBox'>" +
                    "<div class='resultImg'><span class='helper'></span><object data='img/schools/logo" + id + ".png' type='image/png' class='resultLogo'><img src='img/schools/logo.png' class='resultLogo'></object></div>" +
                    "<div class='resultColumn1'><div class='resultName'>" + name + "</div>" +
                    "<div class='resultBachelor" + degree_bachelor + "'></div>" +
                    "<div class='resultMasters" + degree_masters + "'></div>" +
                    "<div class='resultAddress'>" + city + ", " + usstate + "</div>" +
                    "<div class='resultStudents'>Students: " + students + "</div>" +
                    "<div class='resultTuition'>Tuition: $" + tuition_outstate + "/$" + tuition_instate + "</div></div>" +
                    "<div class='resultColumn2'><div class='resultAct'><div class='testLabel'><img src='img/act.png' class='tests'></div><div class='testScore act'>" + act + "</div></div>" +
                    "<div class='resultSat'><div class='testLabel'><img src='img/sat.png' class='tests'></div><div class='testScore sat'>" + sat + "</div></div><div class='testLegend'>Required score</div>" +
                    "<div class='resultAcceptRate'><div class='acceptBar' style='height:"+acceptancerate+"%'></div><div class='acceptLabel' style='bottom:"+acceptancerate+"%'>" + acceptancerate + "%</div></div><div class='acceptLegend'>Accepted</div></div>" +
                    "<div class='resultColumn3'><div class='resultSaveSchool'><a href='saveSchool?id=" + id + "' target='_new' class='btn btn-result btn-save'>Save</a></div>" +
                    "<div class='resultMore'><a href='https://" + url + "' target='_new' class='btn btn-result btn-school-url'>Website</a></div></div>" +
                    "</div>";

                $("#results").append(tr_str);
            }
              },
            error: function (xhr, ajaxOptions, thrownError) {
              alert(xhr.status);
              alert(thrownError);
            }
      });
      }

                  // Loop through our array of markers & place each one on the map, fetching avg_gps_latitude,   avg_gps_longitude from latlngData, received from ajax call ( but it dodn't work)
                  loadLocations().done(function (latlngData) {

                    for (i = 0; i < markers1.length; i++) {
                            markers1[i].setMap(null);
                            }
                            markers1 = [];
                            markers = [];
                            markers = loadLocations();

                      for (i = 0; i < latlngData.length; i++) {
                        //var infoWindow = new google.maps.InfoWindow(), marker;
                        var letter = String.fromCharCode("A".charCodeAt(0) + i - 1);
                        var infoWindow = new google.maps.InfoWindow(), marker, i;
                              var infoWindowContent = '<div class="info_content">' +
                              '<p class="infoWindowName">'+' '+latlngData[i].schoolname+'</p></div>';
                          var tooltip = '';
                          var position = new google.maps.LatLng(latlngData[i].latitude, latlngData[i].longitude);
                          bounds.extend(position);
                          var iconBase = 'img/icons/';
                          var labeltext = latlngData[i].schoolname;
                          marker = new google.maps.Marker({
                              position: position,
                              map: map,
                              label: {
                                color: '#111',
                                text: labeltext,
                                fontSize: '12px'
                          },
                              icon: iconBase + 'marker_black.png'
                              //title: tooltip
                          });
                          markers1.push(marker);

                          // Allow each marker to have an info window
                          google.maps.event.addListener(marker, 'click', (function (marker, infoWindowContent) {
                              return function () {
                                  infoWindow.setContent(infoWindowContent);
                                  infoWindow.open(map, marker);
                              }
                          })(marker, infoWindowContent));
                          // Automatically center the map fitting all markers on the screen
                          //map.fitBounds(bounds);
                      }
                      console.log("loadLocations");
                    });
});
}
</script>

【讨论】:

    【解决方案2】:
        If I understand correctly, there are two thing you want to achieve here. 
    
        1. when initialize the map, get json from server and add makers on it.
        2. when bounds changes, get json and redraws all the maps.
    
        You are very close, I would suggest you to reorganize your code.
    
        1. you need a global array of marks, so you can remove makers from map for redrawing.
    
        ```
        // set globals
        var makers = []
        // clear markers
        function clearMaker (markers) {
          markers.map(m => {m.setmap(null)})
        }
        ```
    
        2. seperate drawMarkers function
        ```
        // drawMarkers
        function drawMarkers(markerJson, markers, map, infowindow) {
          clearMarkers(markers);
          // your draw marker code
        }
        ```
    
        3. Your loadLocation
    
        ```
        /*search location based on geoparams
        geoparam: {
                     a: ne_lat,
                     b: ne_lng,
                     c: sw_lat,
                     d: sw_lng
        }
        */
    
        function loadLocations(geoparam)
        {
                return $.ajax({
                      type:'POST',
                      url: 'includes/newjson.php',
                      dataType: 'json',
                      data: geoparam
                })
          }
        ```
    You can call loadLocation functions when initilize and bounds_changed and it returns a promise.
    
    ```
    loadLocation(geoparams).then((data) => {
      drawMarkers(data, markers, map, inforwindow);
    }).catch(err => { console.log(error)});
    ```
    

    【讨论】:

    • 谢谢你,杰瑞。你正确地理解了我的目标。我将能够在几个小时内进行测试。同时,能否请您说明一下“initilize 和 bounds_changed 时调用 loadLocation 函数”所需的代码?
    • in function initialize() { } 你有你默认的 ne_lng, sw_lng, ne_lat, sw_lat。初始化地图后,您只需使用默认地理参数调用 loadLocation。然后在您的 bounds_change 事件处理程序google.maps.event.addListener(map, 'bounds_changed', function() {}) 中,在您获得新的地理参数后,使用新参数调用 loadLocation。
    • 我已尝试实施更改,但无法使它们生效。当前代码在这个小提琴中:jsfiddle.net/bqm6odog(我已经删除了谷歌地图的 api 密钥。)
    • 澄清一下:没有绘制地图,我得到“未捕获的参考错误:未定义谷歌”,指的是这部分代码:google.maps.event.addListener(map, 'bounds_changed' , function() { loadLocation(geoparams).then((data) => { drawMarkers(data, markers, map, inforwindow); }).catch(err => { console.log(error)}); });
    • 因为你的ajax方法不起作用,所以我没有测试drawMarks函数。但是我为你修复了一些错误。 jsfiddle.net/bqm6odog/4 1. 地图容器必须有固定的高度 2. 你最好使用idle for you bounds change event。
    猜你喜欢
    • 2016-02-12
    • 1970-01-01
    • 2018-11-04
    • 2017-09-21
    • 2012-02-21
    • 1970-01-01
    • 2014-10-18
    • 2013-07-31
    • 1970-01-01
    相关资源
    最近更新 更多