Google Maps 的“map_changed”监听器内部调用的函数被多次调用

Posted

技术标签:

【中文标题】Google Maps 的“map_changed”监听器内部调用的函数被多次调用【英文标题】:The function called inside the 'map_changed' listener of Google Maps is called multiple times 【发布时间】:2021-12-25 19:59:52 【问题描述】:

我将 markerclustererplus 与 Google 地图一起使用。我有多个标记,并且我已将其设置为一次只显示一个 InfoWindow。如果用户单击标记,则会出现一个信息窗口。如果用户缩小并且标记被吸收到一个簇中,则信息窗口将关闭。

我使用标记的“map_changed”侦听器来检查标记是否已被“吸收”到集群中。如果是这样,则 InfoWindow 已关闭,我只想调用另一个函数一次。问题是在我当前的代码中,函数被多个标记调用。

如何才能将“map_changed”侦听器仅添加到当前选定的标记?如果这是不可能的,我怎样才能防止函数被多次调用?我需要暂时 移除未选中标记的“map_changed”监听器?

我要调用的函数名为“closeMarker()”。请查看JSfiddle。

JS:

var map;

function loadMap() 

  map = new google.maps.Map(document.getElementById('map'), 
    center: 
      lat: -41.75,
      lng: 172.75
    ,
    zoom: 4
  );

  addMarkers();

var WeatherStations = [
    "stn": 719460,
    "wban": 99999,
    "StationName": "FORT SIMPSON",
    "FIPS": "CA",
    "Latitude": 61.759998322,
    "Longitude": -121.2369995,
    "Elevation_m": 169,
    "NOAAReadings": 14952
  , 
    "stn": 935970,
    "wban": 99999,
    "StationName": "CAPE CAMPBELL AWS",
    "FIPS": "NZ",
    "Latitude": -41.71699905,
    "Longitude": 174.26699829,
    "Elevation_m": 32,
    "NOAAReadings": 12174
  ,
  
    "stn": 934360,
    "wban": 99999,
    "StationName": "WELLINGTON INTL",
    "FIPS": "NZ",
    "Latitude": -41.32699966,
    "Longitude": 174.80499268,
    "Elevation_m": 12,
    "NOAAReadings": 9914
  , 
    "stn": 937090,
    "wban": 99999,
    "StationName": "HAAST AWS",
    "FIPS": "NZ",
    "Latitude": -43.86700058,
    "Longitude": 169,
    "Elevation_m": 5,
    "NOAAReadings": 14371
  ,
  
    "stn": 935270,
    "wban": 99999,
    "StationName": "FAREWELL SPIT AWS",
    "FIPS": "NZ",
    "Latitude": -40.54999924,
    "Longitude": 173,
    "Elevation_m": 3,
    "NOAAReadings": 11575
  , 
    "stn": 935460,
    "wban": 99999,
    "StationName": "NELSON AERODROME AWS",
    "FIPS": "NZ",
    "Latitude": -41.29999924,
    "Longitude": 173.19999695,
    "Elevation_m": 6,
    "NOAAReadings": 10557
  ,
  
    "stn": 937800,
    "wban": 99999,
    "StationName": "CHRISTCHURCH INTL",
    "FIPS": "NZ",
    "Latitude": -43.48899841,
    "Longitude": 172.53199768,
    "Elevation_m": 38,
    "NOAAReadings": 14933
  , 
    "stn": 938050,
    "wban": 99999,
    "StationName": "PUYSEGUR POINT AWS",
    "FIPS": "NZ",
    "Latitude": -46.15000153,
    "Longitude": 166.6000061,
    "Elevation_m": 44,
    "NOAAReadings": 10493
  ,
  
    "stn": 939940,
    "wban": 99999,
    "StationName": "RAOUL ISLAND AWS",
    "FIPS": "NZ",
    "Latitude": -29.25,
    "Longitude": -177.9329987,
    "Elevation_m": 50,
    "NOAAReadings": 11001
  
];

var styles = [
  [
    url: "https://i.imgur.com/4dzjY47.png",
    height: 47,
    width: 48,
    anchorText: [14, 0],
    textColor: '#fff',
    textSize: 11
  , 
    url: 'https://i.imgur.com/My5Cgpd.png',
    height: 47,
    width: 48,
    anchorText: [14, 0],
    textColor: '#fff',
    textSize: 11
  , 
    url: 'https://i.imgur.com/t7SvOax.png',
    height: 47,
    width: 48,
    anchorText: [14, 0],
    textColor: '#fff',
    textSize: 11
  ]
];

var prev_infowindow = false; // to close previously-opened infowindows
var dataSourceType = 0; // 0 = grid; 1 = weatherstation
var gStn;
var gWban;
var gMarkerLat;
var gMarkerLng;
var gMarkerName;
var iw;
var iwClosed = false;
var curMark;
var infowindow;

function addMarkers() 
  infowindow = new google.maps.InfoWindow();

  var markers = [];

  for (var i = 0; i < WeatherStations.length; i++) 
    var latLng = new google.maps.LatLng(WeatherStations[i].Latitude, WeatherStations[i].Longitude)

    var marker = new google.maps.Marker(
      position: latLng,
      map: map,
      visible: true,
      zIndex: 10,

    );

    var content = "<div id='" + WeatherStations[i].stn + " '> <div class='scrollfix'><b>" + WeatherStations[i].StationName + "</b>";

    google.maps.event.addListener(marker, 'click', (function(marker, content, infowindow) 
      return function() 
        curMark = this;
        // Close already-opened InfoWindow
        if (prev_infowindow) 
          prev_infowindow.close();
        

        prev_infowindow = infowindow;

        infowindow.setContent(content);
        infowindow.setOptions(
          pixelOffset: new google.maps.Size(0, -42)
        )
        infowindow.setPosition(marker.getPosition())
        infowindow.open(map, /* marker */ );
      ;
    )(marker, content, infowindow));


    google.maps.event.addListener(marker, 'map_changed', function() 

      var clusters = markerClusterer.getClusters(); // use the get clusters method which returns an array of objects

      for (let i = 0, l = clusters.length; i < l; i++) 
        const markers = clusters[i].getMarkers();
        for (const m of markers) 
          if (m === curMark && markers.length > 1) 


            try 
              if (infowindow !== null) 

                infowindow.close();
                infowindow = null;
              
              if (prev_infowindow) 
                prev_infowindow.close();
              
                         closeMarker();
             catch (ee) 
          
        
      
    );

    markers.push(marker);
  

  var zoom = null;
  var size = null;
  var style = 0;

  markerClusterer = new MarkerClusterer(map, markers, 
    maxZoom: zoom,
    gridSize: size,
    styles: styles[style]
  );


function clearClusters() 
  markerClusterer.clearMarkers();


function closeMarker()

    console.log('x');

HTML:

<!DOCTYPE html>
    <html>
    <head>
      <title>Google Maps Marker Example</title>
    
    <script src="https://maps.googleapis.com/maps/api/js" async defer></script>
            <script src="https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js"></script>
       <script type="text/javascript" src="mark.js"></script>
      <script>
      
        
      </script>
      <style>
        #map 
          width: 500px;
          height: 500px;
          border: thin solid black;
        
      </style>
    </head>
    <body onload="loadMap();">
      <h1>Google Maps Marker Example</h1>
      <div id="map"></div>
    </body>
    </html>

【问题讨论】:

【参考方案1】:

解决该问题的一种方法是在您关闭变量 null 时将其设置为 null,并将对 closeMark 的调用移至关闭 InfoWindow 并设置 @ 987654327@ 变量为null

另外,不知道你为什么将infowindow 设置为null,但如果你这样做,它只会调用closeMarker 一次。

更新map_changed监听器:

google.maps.event.addListener(marker, 'map_changed', function() 
   var clusters = markerClusterer.getClusters(); // use the get clusters method which returns an array of objects
   for (let i = 0, l = clusters.length; i < l; i++) 
     const markers = clusters[i].getMarkers();
     for (const m of markers) 
       if (m === curMark && markers.length > 1) 
         try 
           if (infowindow !== null) 
             infowindow.close();
             closeMarker();
             curMark=null;
           
           if (prev_infowindow) 
             prev_infowindow.close();
           
          catch (ee) 
      
     
   
);

proof of concept fiddle

代码 sn-p:

var map;

function loadMap() 

  map = new google.maps.Map(document.getElementById('map'), 
    center: 
      lat: -41.75,
      lng: 172.75
    ,
    zoom: 4
  );

  addMarkers();

var WeatherStations = [
    "stn": 719460,
    "wban": 99999,
    "StationName": "FORT SIMPSON",
    "FIPS": "CA",
    "Latitude": 61.759998322,
    "Longitude": -121.2369995,
    "Elevation_m": 169,
    "NOAAReadings": 14952
  , 
    "stn": 935970,
    "wban": 99999,
    "StationName": "CAPE CAMPBELL AWS",
    "FIPS": "NZ",
    "Latitude": -41.71699905,
    "Longitude": 174.26699829,
    "Elevation_m": 32,
    "NOAAReadings": 12174
  ,
  
    "stn": 934360,
    "wban": 99999,
    "StationName": "WELLINGTON INTL",
    "FIPS": "NZ",
    "Latitude": -41.32699966,
    "Longitude": 174.80499268,
    "Elevation_m": 12,
    "NOAAReadings": 9914
  , 
    "stn": 937090,
    "wban": 99999,
    "StationName": "HAAST AWS",
    "FIPS": "NZ",
    "Latitude": -43.86700058,
    "Longitude": 169,
    "Elevation_m": 5,
    "NOAAReadings": 14371
  ,
  
    "stn": 935270,
    "wban": 99999,
    "StationName": "FAREWELL SPIT AWS",
    "FIPS": "NZ",
    "Latitude": -40.54999924,
    "Longitude": 173,
    "Elevation_m": 3,
    "NOAAReadings": 11575
  , 
    "stn": 935460,
    "wban": 99999,
    "StationName": "NELSON AERODROME AWS",
    "FIPS": "NZ",
    "Latitude": -41.29999924,
    "Longitude": 173.19999695,
    "Elevation_m": 6,
    "NOAAReadings": 10557
  ,
  
    "stn": 937800,
    "wban": 99999,
    "StationName": "CHRISTCHURCH INTL",
    "FIPS": "NZ",
    "Latitude": -43.48899841,
    "Longitude": 172.53199768,
    "Elevation_m": 38,
    "NOAAReadings": 14933
  , 
    "stn": 938050,
    "wban": 99999,
    "StationName": "PUYSEGUR POINT AWS",
    "FIPS": "NZ",
    "Latitude": -46.15000153,
    "Longitude": 166.6000061,
    "Elevation_m": 44,
    "NOAAReadings": 10493
  ,
  
    "stn": 939940,
    "wban": 99999,
    "StationName": "RAOUL ISLAND AWS",
    "FIPS": "NZ",
    "Latitude": -29.25,
    "Longitude": -177.9329987,
    "Elevation_m": 50,
    "NOAAReadings": 11001
  
];

var styles = [
  [
    url: "https://i.imgur.com/4dzjY47.png",
    height: 47,
    width: 48,
    anchorText: [14, 0],
    textColor: '#fff',
    textSize: 11
  , 
    url: 'https://i.imgur.com/My5Cgpd.png',
    height: 47,
    width: 48,
    anchorText: [14, 0],
    textColor: '#fff',
    textSize: 11
  , 
    url: 'https://i.imgur.com/t7SvOax.png',
    height: 47,
    width: 48,
    anchorText: [14, 0],
    textColor: '#fff',
    textSize: 11
  ]
];

var prev_infowindow = false; // to close previously-opened infowindows
var dataSourceType = 0; // 0 = grid; 1 = weatherstation
var gStn;
var gWban;
var gMarkerLat;
var gMarkerLng;
var gMarkerName;
var iw;
var iwClosed = false;
var curMark;
var infowindow;

function addMarkers() 
  infowindow = new google.maps.InfoWindow();

  var markers = [];

  for (var i = 0; i < WeatherStations.length; i++) 
    var latLng = new google.maps.LatLng(WeatherStations[i].Latitude, WeatherStations[i].Longitude)

    var marker = new google.maps.Marker(
      position: latLng,
      map: map,
      visible: true,
      zIndex: 10,

    );

    var content = "<div id='" + WeatherStations[i].stn + " '> <div class='scrollfix'><b>" + WeatherStations[i].StationName + "</b>";

    google.maps.event.addListener(marker, 'click', (function(marker, content, infowindow) 
      return function() 
        curMark = this;
        // Close already-opened InfoWindow
        if (prev_infowindow) 
          prev_infowindow.close();
        

        prev_infowindow = infowindow;

        infowindow.setContent(content);
        infowindow.setOptions(
          pixelOffset: new google.maps.Size(0, -42)
        )
        infowindow.setPosition(marker.getPosition())
        infowindow.open(map);
      ;
    )(marker, content, infowindow));


    google.maps.event.addListener(marker, 'map_changed', function() 
      var clusters = markerClusterer.getClusters(); // use the get clusters method which returns an array of objects
      for (let i = 0, l = clusters.length; i < l; i++) 
        const markers = clusters[i].getMarkers();
        for (const m of markers) 
          if (m === curMark && markers.length > 1) 
            try 
              if (infowindow !== null) 

                infowindow.close();
                closeMarker();
                curMark=null;
              
              if (prev_infowindow) 
                prev_infowindow.close();
              
             catch (ee) 
          
        
      
    );

    markers.push(marker);
  

  var zoom = null;
  var size = null;
  var style = 0;

  markerClusterer = new MarkerClusterer(map, markers, 
    maxZoom: zoom,
    gridSize: size,
    styles: styles[style]
  );


function clearClusters() 
  markerClusterer.clearMarkers();


function closeMarker() 
  console.log('x');
<!DOCTYPE html>
<html>
<head>
  <title>Google Maps Marker Example</title>

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk" async defer></script>
        <script src="https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js"></script>
  <style>
    #map 
      width: 500px;
      height: 500px;
      border: thin solid black;
    
  </style>
</head>
<body onload="loadMap();">
  <h1>Google Maps Marker Example</h1>
  <div id="map"></div>
</body>
</html>

【讨论】:

以上是关于Google Maps 的“map_changed”监听器内部调用的函数被多次调用的主要内容,如果未能解决你的问题,请参考以下文章

google maps 单击标记点作为地图中心

google.maps.places.Autocomplete 语言输出

在 maps.google.com 上的缩放比在 Google Maps API v3 上更流畅

Google Maps API DirectionsService.route 与 Google Maps Directions 不同

无法通过 gradle 导入 com.google.maps.android:android-maps-utils

Google Maps API v3 返回 ZERO_RESULTS 但 Maps.Google.com 显示正常