Search code examples
javascripthtmlgoogle-mapsmarkerclusterer

Markerclusterer get cluster size in meters


I am learning google maps in javascript. I am following the tutorial code and so far I have the map with some markers on it which get clustered on zooming out. Here is the code -

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Marker Clustering</title>
    <style>
      #map {
        height: 500px;
      }
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>

      function initMap() {

        var map = new google.maps.Map(document.getElementById('map'), {
          zoom: 3,
          center: {lat: -28.024, lng: 140.887}
        });

        var markers = locations.map(function(location) {
          return new google.maps.Marker({
            position: location
          });
        });

        // Add a marker clusterer to manage the markers.
        var markerCluster = new MarkerClusterer(map, markers,
            {imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'}
        );
        google.maps.event.addListener(markerCluster, 'clusterclick', function(cluster) {
            console.log(markerCluster.getGridSize());
        });
      }
      var locations = [
        {lat: -31.563910, 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.750000, lng: 145.116667},
        {lat: -37.759859, lng: 145.128708},
        {lat: -37.765015, lng: 145.133858},
        {lat: -37.770104, lng: 145.143299},
        {lat: -37.773700, 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.438000},
        {lat: -43.999792, lng: 170.463352}
      ]
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/js-marker-clusterer/1.0.0/markerclusterer_compiled.js">
    </script>
    <script async defer
    src="https://maps.googleapis.com/maps/api/js?key=APIKEYHERE&callback=initMap">
    </script>
  </body>
</html>

I would like to get the cluster size when I click on the cluster,which as of now I am using getGridSize to get,but it returns the value in pixels. Is there anyway I can get this value in meters or kilometers?


Solution

  • You should probably use MarkerClustererPlus which is more recent than what you are using https://github.com/googlemaps/v3-utility-library/tree/master/packages/markerclustererplus

    You can use the overlay created by the Marker Clusterer and use its projection to convert 2 points separated by n pixels, where n is your grid size. You can use the fromContainerPixelToLatLng method for that.

    Then you can compute the distance between the 2 LatLng points by using the Geometry library (you need to include it with the API call) by using the computeDistanceBetween method.

    Proof of concept: here

    var map;
    var markers = [];
    var markerCluster;
    
    function initialize() {
    
      var center = new google.maps.LatLng(0, 0);
    
      map = new google.maps.Map(document.getElementById('map'), {
        zoom: 3,
        minZoom: 1,
        center: center,
        scaleControl: true,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      });
    
      // Cluster all the markers
      markerCluster = new MarkerClusterer(map, markers, {
        imagePath: 'https://ccplugins.co/markerclusterer/images/m',
        gridSize: 100,
        minimumClusterSize: 10
      });
    
      google.maps.event.addListener(map, 'idle', function() {
    
        getGridSizeInMeters();
      });
    }
    
    function getGridSizeInMeters() {
    
      var size = markerCluster.getGridSize();
    
      var p1 = markerCluster.getProjection().fromContainerPixelToLatLng(new google.maps.Point(0, 0));
      var p2 = markerCluster.getProjection().fromContainerPixelToLatLng(new google.maps.Point(0, size));
    
      var meters = google.maps.geometry.spherical.computeDistanceBetween(p1, p2);
    
      console.log('Grid size is %i meters / %i kilometers', meters, meters / 1000);
    }
    
    google.maps.event.addDomListener(window, 'load', initialize);
    #map {
      height: 180px;
    }
    <div id="map"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/markerclustererplus/2.1.4/markerclusterer.min.js"></script>
    <!-- Replace the value of the key parameter with your own API key. -->
    <script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initialize" async defer></script>

    Warning though, as depending on the zoom level, the latitude, and therefore the part of the map projection on which you do the calculation, you might get very different results due to the Mercator projection.