如何使用 Google 地图 API 一次只看到 10 个标记,而不考虑地图 view/zoom

How to only see 10 markers at a time with Google Maps API regardless of map view/zoom

我希望改进我的网络应用程序中的 Google 地图。我在地图上有大约 200 个标记,但显然这在视觉上并不吸引人。我想知道是否有一种方法可以根据变量 Celsius 在其上只显示 10 个标记?因此,如果地图基于整个世界视图,您会看到记录了 10 个最高温度的标记。如果您移动到世界地图上的另一部分或放大,我希望标记能够更新。

这可能吗?我试图通过包含最多 10 个标记来做到这一点,但我无法使其成为动态的,因为当我添加标记时,我通过 JSON 文件进行解析。其中有以下输出 {"AA": {"celsius": 32.27777777777778, "country": "AA", "day": "25", "lat": 12.5 , "lon": -70.017, "month": "03"}.

这是我最后一个功能齐全的代码..

    // 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
  google.maps.event.addListener(map, 'zoom_changed', function() {

    // Handle markers display
    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
       });

       // 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;

           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;
      });

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

function handleMarkersDisplay() {

  // Check if map current zoom <= 2
  if (map.getZoom() <= 2) {

    // Loop through markers array
    for (var i = 0; i < markers.length; i++) {

      // Only show the first 10 markers
      if (i < 10) {
        markers[i].setVisible(true);
      } else {
        markers[i].setVisible(false);
      }
    }
  } else if (map.getZoom() == 3) {

    // Loop through markers array
    for (var i = 0; i < markers.length; i++) {

      // Only show the first 10 markers
      if (i < 10) {
        markers[i].setVisible(true);
      } else {
        markers[i].setVisible(false);
      }
    }
  } else if (map.getZoom() == 4) {

    // Loop through markers array
    for (var i = 0; i < markers.length; i++) {

      // Only show the first 10 markers
      if (i < 10) {
        markers[i].setVisible(true);
      } else {
        markers[i].setVisible(false);
      }
    }
  } else if (map.getZoom() == 5) {

    // Loop through markers array
    for (var i = 0; i < markers.length; i++) {

      // Only show the first 10 markers
      if (i < 10) {
        markers[i].setVisible(true);
      } else {
        markers[i].setVisible(false);
      }
    }
  } else if (map.getZoom() == 6) {

    // Loop through markers array
    for (var i = 0; i < markers.length; i++) {

      // Only show the first 10 markers
      if (i < 10) {
        markers[i].setVisible(true);
      } else {
        markers[i].setVisible(false);
      }
    }
  } else if (map.getZoom() == 7) {

    // Loop through markers array
    for (var i = 0; i < markers.length; i++) {

      // Only show the first 10 markers
      if (i < 10) {
        markers[i].setVisible(true);
      } else {
        markers[i].setVisible(false);
      }
    }
  } else if (map.getZoom() == 8 ) {

    // Loop through markers array
    for (var i = 0; i < markers.length; i++) {

      // Only show the first 10 markers
      if (i < 10) {
        markers[i].setVisible(true);
      } else {
        markers[i].setVisible(false);
      }
    }
  } else if (map.getZoom() == 9) {

    // Loop through markers array
    for (var i = 0; i < markers.length; i++) {

      // Only show the first 10 markers
      if (i < 10) {
        markers[i].setVisible(true);
      } else {
        markers[i].setVisible(false);
      }
    }
  } else if (map.getZoom() == 10) {

    // Loop through markers array
    for (var i = 0; i < markers.length; i++) {

      // Only show the first 10 markers
      if (i < 10) {
        markers[i].setVisible(true);
      } else {
        markers[i].setVisible(false);
      }
    }
  } else {

    // Zoom is greater than 3, show all markers
    for (var i = 0; i < markers.length; i++) {

      markers[i].setVisible(true);
    }
  }
}

你需要两样东西:

  1. 将摄氏度值作为 属性
  2. 添加到每个标记对象
  3. 将每个 Marker 对象添加到一个标记数组中,这样您就可以保留对它们的引用

Google 地图 API 提供多个 events 供您收听。其中之一是 zoom_changed 事件。有了这个,您可以遵循以下逻辑:

  1. 请求数据 AJAX
  2. 创建每个 Marker 对象并将其可见性设置为 false
  3. 将摄氏度值添加为标记 属性
  4. 将每个标记添加到标记数组

完成此操作并创建所有标记后:

  1. 按摄氏度值对标记数组排序
  2. 检查当前缩放级别
  3. 如果缩放级别低于 n,循环标记并仅显示 n
  4. 如果缩放级别高于 n,遍历标记并全部显示它们

并在用户通过监听 zoom_changed 事件更改缩放级别时重复该逻辑。

下面的工作示例如果缩放 <= 2 将仅显示 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
  google.maps.event.addListener(map, 'zoom_changed', function() {

    // Handle markers display
    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
        });

        // 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;

            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;
      });

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

function handleMarkersDisplay() {

  // Check if map current zoom <= 2
  if (map.getZoom() <= 2) {

    // Loop through markers array
    for (var i = 0; i < markers.length; i++) {

      // Only show the first 10 markers
      if (i < 10) {
        markers[i].setVisible(true);
      } else {
        markers[i].setVisible(false);
      }
    }
  } else {

    // Zoom is greater than 2, show all markers
    for (var i = 0; i < markers.length; i++) {

      markers[i].setVisible(true);
    }
  }
}
#map {
  height: 180px;
}
<div id="map"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- 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>