如何更新我的功能,使 Google 地图上始终有 10 个标记,无论缩放和视图如何(Mashup 使用 CS50)

How to update my function so that there are always 10 markers on Google Maps regardless of zoom and view (Mashup used CS50)

这是我让它工作的更新后的最终代码。我使用 get.zoom 和 center.change 来确保无论地图的视图如何,地图上总会有 10 个标记! (原题如下

'''


    // Declare map and markers array globally
var map, markers = [];

function initMap() {

  var myLatLng = {
    lat: 0,
    lng: 0
  };

  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 2,
    center: myLatLng,
    zoomControl: true
  });

  // Moved this out of the AJAX success and declared variable correctly
  var infowindow = new google.maps.InfoWindow();

  // Listen for zoom change event
  // Handle markers display
  google.maps.event.addListener(map, 'zoom_changed', handleMarkersDisplay);

  $.ajax({
    type: 'GET',
    url: 'https://us-central1-cloud-calendar-project.cloudfunctions.net/InfoWindow',
    success: function(data) {

      data = JSON.parse(data);

      for (var element in data) {
        var marker = new google.maps.Marker({
          position: {
            lat: data[element].lat,
            lng: data[element].lon
          },
          map: map,
          title: element,
          visible: false, // Default visibility is false
          marker_celsius: data[element].celsius // Add celsius as marker property
        });
        console.log("marker@" + marker.getPosition().toUrlValue());
        // Push this marker to the markers array
        markers.push(marker);

        google.maps.event.addListener(marker, 'click', (function(marker, element) {

          return function() {

            var content = 'Country: ' + data[element].country;
            content += '<br>Temperature (°C): ' + data[element].celsius;
            content += '<br>Day: ' + data[element].day;
            content += '<br>Month: ' + data[element].month;

            infowindow.setContent(content);
            infowindow.open(map, marker);
          }

        })(marker, element));
      }

      // All markers have been added, sort the markers array by celsius value
      markers.sort(function(a, b) {
        return b.marker_celsius - a.marker_celsius;
      });
      map.addListener('center_changed', function() {
      window.setTimeout(handleMarkersDisplay() , 3000);
      });

      // Handle markers display
      handleMarkersDisplay();
    }
  });
}



function handleMarkersDisplay() {
  console.log("handleMarkerDisplay zoom=" + map.getZoom());
  // Check if map current zoom <= 2
  if (map.getZoom() <= 2) {
    hideAllMarkers();
    displayMarkers();
  } else if (map.getZoom() == 3) {
    hideAllMarkers();
    displayMarkers();
  } else if (map.getZoom() == 4) {
    hideAllMarkers();
    displayMarkers();
  } else if (map.getZoom() == 5) {
    hideAllMarkers();
    displayMarkers();
  }
}

function hideAllMarkers() {
  for (i = 0; i < markers.length; i++) {
    markers[i].setVisible(false);
  }
}

function displayMarkers() {
  // add new markers to map
  var shownMarkers = 10;
  for (var i = 0; i < markers.length; i++) {
    // Only show the first 10 markers in the viewport
    if (shownMarkers > 0) {
      if (map.getBounds().contains(markers[i].getPosition())) {
        markers[i].setVisible(true);
        shownMarkers--;
      }
    } else {
      markers[i].setVisible(false);
    }
  }
}

function displayAllMarkers() {
  // Zoom is greater than 3, show all markers
  for (var i = 0; i < markers.length; i++) {
    markers[i].setVisible(true);
  }
}

'''

我正在开发一个 Web 应用程序,我想根据记录的最高温度(来自我解析的 JSON 文件)在地图上显示标记。目前,我能够在地图上获得 10 个最高温度标记,但是当我放大时,它不会更新以添加新标记。因此,当我放大一个时,视图中的标记从 10 个增加到 8 个(您需要滚动才能看到其他两个标记)。我想添加两个新标记,它们对应于该视图的下一个最高标记,这样无论 view/zoom 你有什么,你总能看到 10 个标记! (在某种程度上可能是不可能的,例如只能看到一个国家)。下图展示了在缩放 3 时,两个标记被遗漏在视野之外。 我通过 endiliey 找到了这个实现 (https://github.com/endiliey/cs50/blob/master/pset8/mashup/static/scripts.js)。然而,实施不起作用..

如果你想在视口中显示最高的 10 个标记,你需要计算那些:

function displayMarkers() {
  // add new markers to map
  var shownMarkers = 10;
  for (var i = 0; i < markers.length; i++) {
    // Only show the first 10 markers in the viewport
    if (shownMarkers > 0) {
      if (map.getBounds().contains(markers[i].getPosition())) {
        markers[i].setVisible(true);
        shownMarkers--;
      } else {
        markers[i].setVisible(false);
      }
    } else {
      markers[i].setVisible(false);
    }
  }
}

然后在加载新标记或更新缩放时调用该函数:

proof of concept fiddle

代码片段:

// Declare map and markers array globally
var map, markers = [];

function initMap() {

  var myLatLng = {
    lat: 0,
    lng: 0
  };

  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 2,
    center: myLatLng,
    zoomControl: true
  });

  // Moved this out of the AJAX success and declared variable correctly
  var infowindow = new google.maps.InfoWindow();

  // Listen for zoom change event
  // Handle markers display
  google.maps.event.addListener(map, 'zoom_changed', handleMarkersDisplay);

  $.ajax({
    type: 'GET',
    url: 'https://us-central1-cloud-calendar-project.cloudfunctions.net/InfoWindow',
    success: function(data) {
      removeMarkers();
      data = JSON.parse(data);

      for (var element in data) {
        var marker = new google.maps.Marker({
          position: {
            lat: data[element].lat,
            lng: data[element].lon
          },
          map: map,
          title: element,
          visible: false, // Default visibility is false
          marker_celsius: data[element].celsius // Add celsius as marker property
        });
        console.log("marker@" + marker.getPosition().toUrlValue());
        // Push this marker to the markers array
        markers.push(marker);

        google.maps.event.addListener(marker, 'click', (function(marker, element) {

          return function() {

            var content = 'Country: ' + data[element].country;
            content += '<br>Temperature (°C): ' + data[element].celsius;
            content += '<br>Day: ' + data[element].day;
            content += '<br>Month: ' + data[element].month;

            infowindow.setContent(content);
            infowindow.open(map, marker);
          }

        })(marker, element));
      }

      // All markers have been added, sort the markers array by celsius value
      markers.sort(function(a, b) {
        return b.marker_celsius - a.marker_celsius;
      });
      console.log("loaded "+markers.length+" markers");
      // Handle markers display
      handleMarkersDisplay();
    }
  });
}

function handleMarkersDisplay() {
  console.log("handleMarkerDisplay zoom=" + map.getZoom());
  // Check if map current zoom <= 2
  if (map.getZoom() <= 5) {
    displayMarkers();
  } else {
    displayAllMarkers();
  }
}

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

function hideAllMarkers() {
  for (i = 0; i < markers.length; i++) {
    markers[i].setVisible(false);
  }
}

function displayMarkers() {
  // add new markers to map
  var shownMarkers = 10;
  for (var i = 0; i < markers.length; i++) {
    // Only show the first 10 markers in the viewport
    if (shownMarkers > 0) {
      if (map.getBounds().contains(markers[i].getPosition())) {
        markers[i].setVisible(true);
        shownMarkers--;
      } else {
        markers[i].setVisible(false);
      }
    } else {
      markers[i].setVisible(false);
    }
  }
}

function displayAllMarkers() {
  // Zoom is greater than 3, show all markers
  for (var i = 0; i < markers.length; i++) {
    markers[i].setVisible(true);
  }
}
/* Always set the map height explicitly to define the size of the div
 * element that contains the map. */
#map {
  height: 100%;
}

/* Optional: Makes the sample page fill the window. */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap" async defer></script>