Search code examples
javascriptgoogle-mapsmarkerclusterer

Google Map js API set new clusters on click


Here are 2 Array with Latitude and Longitude.

const locations1 = [
     { lat: -31.56391, lng: 147.154312 },
     { lat: -33.718234, lng: 150.363181 },
     { lat: -33.727111, lng: 150.371124 },
     { lat: -33.848588, lng: 151.209834 },
     { lat: -33.851702, lng: 151.216968 },
    ];

const locations2 = [
  { lat: -37.7737, lng: 145.145187 },
  { lat: -37.774785, lng: 145.137978 },
  { lat: -37.819616, lng: 144.968119 },
  { lat: -38.330766, lng: 144.695692 },
  { lat: -39.927193, lng: 175.053218 },
];

which i am trying to load at a time by clearing previous clusters when clicked on button.

Library link as recommended by google: https://github.com/googlemaps/js-markerclustererplus

For some some reason, when i click button, it adds new clusters but doesn't clears old one. pre-existing clusters image

Here is my code:

//on click button clear and load again

  const refresh = document.querySelector('#clearbtn');
  refresh.addEventListener("click", () => {
        
    const clear =   setClusters(markers);   
    clear.clearMarkers();
    const markersNew = setMarkers(locations2);
    setClusters(markersNew);
        
    });

 }

Here is full code:

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 2,
    center: {
      lat: -28.024,
      lng: 140.887
    },
  });
  // Create an array of alphabetical characters used to label the markers.
  const labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  // Add some markers to the map.
  // Note: The code uses the JavaScript Array.prototype.map() method to
  // create an array of markers based on a given "locations" array.
  // The map() method here has nothing to do with the Google Maps API.
  const setMarkers = (setmarkers) => {
    return setmarkers.map((location, i) => {
      return new google.maps.Marker({
        position: location,
        label: labels[i % labels.length],
      });
    })
  };

  // Add a marker clusterer to manage the markers.
  const setClusters = (setclusters) => {
    return new MarkerClusterer(map, setclusters, {
      imagePath: "https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m",
    })
  };

  const markers = setMarkers(locations1);

  markerClusterer = setClusters(markers);


  //on click button clear and load again
  const refresh = document.querySelector('#clearbtn');
  refresh.addEventListener("click", () => {

    const clear = setClusters(markers);

    clear.clearMarkers();

    const markersNew = setMarkers(locations2);

    setClusters(markersNew);

  });

}



const locations1 = [{
    lat: -31.56391,
    lng: 147.154312
  },
  {
    lat: -33.718234,
    lng: 150.363181
  },
  {
    lat: -33.727111,
    lng: 150.371124
  },
  {
    lat: -33.848588,
    lng: 151.209834
  },
  {
    lat: -33.851702,
    lng: 151.216968
  },
  {
    lat: -34.671264,
    lng: 150.863657
  },
  {
    lat: -35.304724,
    lng: 148.662905
  },
  {
    lat: -36.817685,
    lng: 175.699196
  },
  {
    lat: -36.828611,
    lng: 175.790222
  },
  {
    lat: -37.75,
    lng: 145.116667
  },
  {
    lat: -37.759859,
    lng: 145.128708
  }
];

const locations2 = [

  {
    lat: -37.7737,
    lng: 145.145187
  },
  {
    lat: -37.774785,
    lng: 145.137978
  },
  {
    lat: -37.819616,
    lng: 144.968119
  },
  {
    lat: -38.330766,
    lng: 144.695692
  },
  {
    lat: -39.927193,
    lng: 175.053218
  },
  {
    lat: -41.330162,
    lng: 174.865694
  },
  {
    lat: -42.734358,
    lng: 147.439506
  },
  {
    lat: -42.734358,
    lng: 147.501315
  },
  {
    lat: -42.735258,
    lng: 147.438
  },
  {
    lat: -43.999792,
    lng: 170.463352
  }
];
/* Always set the map height explicitly to define the size of the div
       * element that contains the map. */

#map {
  height: 70%;
}

#clearbtn {
  display: flex;
  flex-wrap: no-wrap;
  justify-content: center;
  /* height: 40px; */
  background: #3498db;
  padding: 15px 45px;
  margin: 20px 100px;
  color: #fff;
  text-decoration: none;
  font-size: 18px;
}


/* Optional: Makes the sample page fill the window. */

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
<!DOCTYPE html>
<html>

<head>
  <title>Marker Clustering</title>
  <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
  <script src="https://unpkg.com/@google/[email protected]/dist/markerclustererplus.min.js"></script>

  <!-- jsFiddle will insert css and js -->
</head>

<body>
  <div id="map"></div>

  <!-- Async script executes immediately and must be after any DOM elements used in callback. -->
  <a href="#" id="clearbtn">Refresh with new markers</a>
  <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=&v=weekly" async></script>
</body>

</html>


Solution

  • You are creating a new/second marker clusterer, then removing the markers on it. Keep a reference to the first marker clusterer you create, that will enable you to remove those markers.

    your existing code:

    //on click button clear and load again
    
      const refresh = document.querySelector('#clearbtn');
      refresh.addEventListener("click", () => {
            
        const clear =   setClusters(markers);   // creates new/different MarkerClusterer
        clear.clearMarkers();
        const markersNew = setMarkers(locations2);
        setClusters(markersNew);
            
        });
    
     }
    

    instead you can do this:

    let markerClusterer = null;  // in the global scope.
    
    // ...
    const markers = setMarkers(locations1);
     
    markerClusterer = setClusters(markers);
      
      //on click button clear and load again
    const refresh = document.querySelector('#clearbtn');
      refresh.addEventListener("click", () => {
            
        markerClusterer.clearMarkers();
        const markersNew = setMarkers(locations2);
        setClusters(markersNew);
            
    });
    

    updated fiddle

    before clicking the "refresh" button: before clicking "refresh"

    after clicking the "refresh" button:

    after clicking "refresh"

    code snippet:

    let markerClusterer = null;
    function initMap() {
      const map = new google.maps.Map(document.getElementById("map"), {
        zoom: 2,
        center: { lat: -28.024, lng: 140.887 },
      });
      // Create an array of alphabetical characters used to label the markers.
      const labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
      // Add some markers to the map.
      // Note: The code uses the JavaScript Array.prototype.map() method to
      // create an array of markers based on a given "locations" array.
      // The map() method here has nothing to do with the Google Maps API.
      const setMarkers = (setmarkers) => {return setmarkers.map((location, i) => {
        return new google.maps.Marker({
          position: location,
          label: labels[i % labels.length],
        });
      })};
        
      // Add a marker clusterer to manage the markers.
      const setClusters = (setclusters) => {
        return new MarkerClusterer(map, setclusters, {
        imagePath: 'https://unpkg.com/@google/[email protected]/images/m',
      }) 
        };
      
      const markers = setMarkers(locations1);
      
      markerClusterer = setClusters(markers);
    
      
      //on click button clear and load again
      const refresh = document.querySelector('#clearbtn');
      refresh.addEventListener("click", () => {
            
        markerClusterer.clearMarkers();
        
        const markersNew = setMarkers(locations2);
        
        setClusters(markersNew);
            
        });
    
     }
    
    
    
    const locations1 = [
      { lat: -31.56391, lng: 147.154312 },
      { lat: -33.718234, lng: 150.363181 },
      { lat: -33.727111, lng: 150.371124 },
      { lat: -33.848588, lng: 151.209834 },
      { lat: -33.851702, lng: 151.216968 },
      { lat: -34.671264, lng: 150.863657 },
      { lat: -35.304724, lng: 148.662905 },
      { lat: -36.817685, lng: 175.699196 },
      { lat: -36.828611, lng: 175.790222 },
      { lat: -37.75, lng: 145.116667 },
      { lat: -37.759859, lng: 145.128708 }
    ];
    
    const locations2 = [
      
      { lat: -37.7737, lng: 145.145187 },
      { lat: -37.774785, lng: 145.137978 },
      { lat: -37.819616, lng: 144.968119 },
      { lat: -38.330766, lng: 144.695692 },
      { lat: -39.927193, lng: 175.053218 },
      { lat: -41.330162, lng: 174.865694 },
      { lat: -42.734358, lng: 147.439506 },
      { lat: -42.734358, lng: 147.501315 },
      { lat: -42.735258, lng: 147.438 },
      { lat: -43.999792, lng: 170.463352 }
    ];
    /* Always set the map height explicitly to define the size of the div
           * element that contains the map. */
    #map {
      height: 70%;
    }
    
    #clearbtn{
      display: flex;
      flex-wrap: no-wrap;
      justify-content: center;
      /* height: 40px; */
      background: #3498db;
      padding: 15px 45px;
      margin: 20px 100px;
      color: #fff;
      text-decoration: none;
      font-size: 18px;
    }
    
    /* Optional: Makes the sample page fill the window. */
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    <!DOCTYPE html>
    <html>
      <head>
        <title>Marker Clustering</title>
        <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
        <script src="https://unpkg.com/@google/[email protected]/dist/markerclustererplus.min.js"></script>
    
        <!-- jsFiddle will insert css and js -->
      </head>
      <body>
        <div id="map"></div>
    
        <!-- Async script executes immediately and must be after any DOM elements used in callback. -->
         <a href="#" id="clearbtn">Refresh with new markers</a>
        <script
          src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=&v=weekly"
          async
        ></script>
      </body>
    </html>