如何更新我的功能,以便无论缩放和视图如何,谷歌地图上总是有 10 个标记(混搭使用 CS50)

Posted

技术标签:

【中文标题】如何更新我的功能,以便无论缩放和视图如何,谷歌地图上总是有 10 个标记(混搭使用 CS50)【英文标题】:How to update my function so that there are always 10 markers on Google Maps regardless of zoom and view (Mashup used CS50) 【发布时间】:2020-07-22 23:33:18 【问题描述】:

这是我让它工作的更新后的最终代码。我使用 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 个标记(您需要滚动才能看到其他两个标记)。我想添加两个新标记,它们对应于该视图的下一个最高标记,这样无论您使用何种视图/缩放,您总能看到 10 个标记! (在某种程度上可能是不可能的,例如只看到一个国家)。下图展示了在缩放 3 时,两个标记不在视野范围内。 我通过 endiliey 找到了这个实现 (https://github.com/endiliey/cs50/blob/master/pset8/mashup/static/scripts.js)。但是,实施不起作用..

【问题讨论】:

您应该将原始代码留在出现问题的问题中(供未来的读者使用)。 【参考方案1】:

如果要在视口中显示最高的 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

代码 sn-p:

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

【讨论】:

以上是关于如何更新我的功能,以便无论缩放和视图如何,谷歌地图上总是有 10 个标记(混搭使用 CS50)的主要内容,如果未能解决你的问题,请参考以下文章

无论如何在谷歌地图上计算英里或米到像素以计算缩放级别?

如何设置谷歌地图缩放级别以显示所有标记?

谷歌地图视图如何在地图缩放时获取原始点或框进行注释?

Android:如何将地图视图的缩放级别设置为当前位置周围 1 公里半径?

如何在滚动视图中设置谷歌地图片段

如何将地图视图中已缩放的位置更改为当前设备位置