Google Maps Marker Clustering
Development | Krunoslav Peulic

Google Maps Marker Clustering

Friday, Dec 29, 2017 • 3 min read
How to use Google Maps marker clustering to display a large number of markers on your maps.

In this article, you will learn how to use Google Maps marker clustering to show a lot of markers on a map. We assume that you are familiar with Google Maps and Google Maps Markers. If not, you can read more about it in Google Maps JavaScript API - Intro.

Forest or trees?

It is great to have the ability to show a bunch of markers (locations) in an area, but what if we have too many markers to display? If that’s the case, we’ll have a forest, and won’t be able to see a tree.

Styled map

To avoid the forest issue, we’ll try to group all the markers in an area on the map and show a specific amount of them. As we zoom into cluster locations, we’ll be able to see the dispersion of markers and clusters around the area.

Styled map

Default markers clustering

The simplest way to get a sense of how it works is to use basic locations format with lat and lng properties:

var locations = [
    {lat: 40.733711, lng: -74.000924},
    {lat: 40.7419449, lng: -73.9966639},
    {lat: 40.80343810000001, lng: -73.9545847},
    {lat: 40.76064179999999, lng: -73.9962596},
    {lat: 40.7694349, lng: -73.9886707},
    {lat: 40.7928421, lng: -73.96588950000002},
    {lat: 40.7268495, lng: -73.978535},
    {lat: 40.7994527, lng: -73.9688133}
]

After that, we can set up an initial map with default JavaScript library for the MarkerClusterer from Google Maps repo on GitHub and Google Maps JavaScript API:

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

<script>
    function initMap() {
        var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 10,
            center: { lat: 40.779033, lng: -73.962297 }
        });
    }
</script>

<script src="https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js"></script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script>

To add a few markers to the map, use:

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

Now we are ready to create marker clusterer using the function MarkerClusterer and the property imagePath to define the cluster layout:

var markerCluster = new MarkerClusterer(map, markers,
    {imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'});

As a result you’ll get this:

Styled map

You can get a finished code sample here.

Custom markers clustering

Since we weren’t satisfied with the default solution, we made some customization to the default setup. First of all, the static locations didn’t suit us, so we found a better solution - the GeoJSON format. It supports a couple of geometry types, but we will use only the Point format to show the markers on our map.

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [40.779033, -73.962297]
  },
  "properties": {
    "name": "New York City"
  }
}

The main reason why we chose the GeoJSON format was the fact that google.maps.Data class has a built-in method loadGeoJson, which can load GeoJSON from a URL - so we created a service on our side which will provide us with locations from our database.

{
    "features": [
        {
            "geometry": {
                "coordinates": [
                    -73.994265,
                    40.7618509
                ],
                "type": "Point"
            },
            "properties": {
                "address": "639 10th Avenue"
            },
            "type": "Feature"
        },
        {
            "geometry": {
                "coordinates": [
                    -73.967482,
                    40.68906
                ],
                "type": "Point"
            },
            "properties": {
                "address": "295 Clinton Avenue"
            },
            "type": "Feature"
        },
        ...
    ],
    "type": "FeatureCollection"
}

Our script to fill the map with markers from GeoJSON data will look like this:

function initMap() {
        var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 10,
            center: { lat: 40.779033, lng: -73.962297 }
        });

        map.data.loadGeoJson('my-locations.json');
    }

To create markers clustering with the data from my-locations.json, we need to extend the loadGeoJson method a little bit:

map.data.loadGeoJson('my-locations.json', null, function (features){
    markers = features.map(function(feature) {
        return new google.maps.Marker({
            position: feature.getGeometry().get(0)
        });
    });

    var markerCluster = new MarkerClusterer(map, markers,
        {imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'});
});

To avoid collision of the markers and clusters during the zoom in/out process, we need to remove unnecessary features from the map using:

map.data.setMap(null);

As a result, you’ll get this:

Styled map

You can get a complete code sample here.

Homework - dynamic cluster size

Since we weren’t satisfied with the clusters layout, we found a way to change the default styling. Our goal was to have a dynamic cluster size - depending on the number of markers in a certain area and to ensure this behavior, you need to download the default markerclusterer.js script and change ClusterIcon.prototype.createCss function using our custom code:

ClusterIcon.prototype.createCss = function (pos) {
    var size = 15;
    if (this.cluster_.getMarkers().length < 10) { size = 15; }
    if (this.cluster_.getMarkers().length > 10 && this.cluster_.getMarkers().length < 100) { size = 22; }
    if (this.cluster_.getMarkers().length > 100 && this.cluster_.getMarkers().length < 1000) { size = 30; }
    if (this.cluster_.getMarkers().length > 1000) { size = 37; }

      style = ['border-radius : 50%',
        'cursor        : pointer',
        'position      : absolute',
        'top           : ' + pos.y + 'px',
        'left          : ' + pos.x + 'px',
        'width         : ' + size * 2 + 'px',
        'height        : ' + size * 2 + 'px',
        'line-height   : ' + (size * 2 + 1) + 'px',
        'text-align    : center',
        'background-color: #51B3C3',
        'color: #ffffff',
        'font-size:14px'
      ];
    return style.join(";") + ';';
};

For your homework, we encourage you to play with our marker’s length thresholds, cluster sizes, and cluster colors. Your result should be something like this:

Styled map