in Code, HowTo

Clustering Markers On Leaflet Maps

So you’re creating an interactive map using Leaflet and have diligently added your 8107 markers to the map.

Leaflet - Too Many Markers!

Leaflet – Too Many Markers!

Uh-oh. Definitely slow and pretty much doesn’t provide a user experience. What do we do now?

There’s a great plugin for Leaflet called Leaflet.markercluster by Dave Leaver which will save us.

Leaflet Clusters

Leaflet Clusters

This plugin clusters the markers and shows the number of items in each cluster, and as we zoom it adjusts the clusters based on the current view. This not only makes the map easier for the user to understand, it’s also a lot more efficient.

If you followed my previous Leaflet tutorial, adding the clustering plugin is extremely simple. Let’s take a look.

Leaflet.markercluster has some cool capabilities. By default, hovering the mouse over an area outlines the area like this:

Leaflet Clusters - Hovering

Leaflet Clusters – Hovering

Clicking inside an area zooms in and shows you the next level of clusters:

Leaflet Clusters - Zoom In

Leaflet Clusters – Zoom In

When a cluster only has one item in it, it shows it as a marker:

Leaflet Clusters - Zoom In Again!

Leaflet Clusters – Zoom In Again!

And of course, like the last example, clicking a marker shows more information about the location:

Leaflet Popup

Leaflet Popup

For this example, I’m going to create a map showing the airports and train stations of the world. I grabbed a data set from OpenFlights.org which gives locations and other information for airports and train stations. I downloaded the CSV, converted it to JSON, and collapsed it a bit since it’s rather large.

This example consists of three files and two images:

  • index.html – the page itself
  • maps/leaf-demo.js – JavaScript to create the map and populate it with markers
  • maps/markers.js – a list of markers with their latitude & longitude as well as other info about the location to display in the popup when you click a marker
  • maps/images/pin24.png and pin48.png – the pin to display (one for normal display, one for retina)

(The files used in this example are available on GitHub. Note that the version on GitHub will look different that what is outlined here since it has been updated to use more recent versions of the libraries. I recommend using it instead of copying the code on this page.)

The HTML

Let’s start by taking a look at the HTML. This is pretty much the same as the example in the last post and should be fairly straightforward.

The only significant changes here are that I added two stylesheets and one javascript for leaflet.markercluster. If you want to customize the look of the cluster indicators, you can override the stylesheets.

The Leaflet JavaScript

The first part of this is the same as the last example. We create the map, set up the tiles, and create our icon.

And here are the changes needed for adding clustering:

Line 22 creates a cluster group. There are several options which can be passed here to customize it.

Next, for each element in the JSON data, we create a marker on the map, set the popup for it to display additional information, and add it to a new layer in the cluster group.

Finally in line 39 we add the cluster group as a layer on the map.

That’s it. We’re done.

The JSON Data

As I mentioned above, I downloaded a data set from OpenFlights.org and converted it to JSON data. I made this into a JavaScript file which just sets a variable. This lets us include this file as straight Javascript and to use the markers variable as-is.

Final Result

Try it out!

I hope this is useful to someone out there in and amongst this series of tubes we call The Internet.

(The files used in this example are available on GitHub. Note that the version on GitHub will look different that what is outlined here since it has been updated to use more recent versions of the libraries. I recommend using it instead of copying the code on this page.)

As always, if you have suggestions on how to improve my code or make things easier, please comment below or feel free to contact me.

Update 06 May 2021 (GitHub code):

  • Updated to Leaflet 1.7.1, leaflet.markercluster 1.5.0, and jQuery 3.6.0.
  • Added Subresource Integrity to CSS and CDN JavaScript.
  • All files reformatted with prettier.
  • Use https for URLs.

Update 12 July 2016: MapQuest discontinued the tile set I was using, so I switched to OpenStreetMap’s tiles. Note that these are useful only for testing. They say on their site:

Apart from very limited testing purposes, you should not use the tiles supplied by OpenStreetMap.org itself.

Update 12 July 2016: Updated example to use Leaflet 0.7.7 (no code changes, just including newer version of javascript).

Leave a Reply for Dhamo Cancel Reply

Write a Comment

Comment

45 Comments

  1. How can i set the minWidth of the Popup.
    Documentation of Leaflet says:
    var popup = L.popup(minWidth:500);
    But in your script : var popup = markers[i].name + etc.etc.

    • I haven’t tried it, but this answer says you can do the following:

  2. Great project. Quick question – sometimes I have noticed after I created my own local copy using the files, when I zoom in or out, occasionally some of the group markers and some of the markers that should display as the lowest level markers also don’t appear.

    I hit F5 and it resets everything.

    Any thoughts?
    Cheers

  3. Hi,
    Today my site upgraded to https secured site. My starting page kept empty.I use leaflet V0.4.0 and Markercluster V0.7.7. After upgrade leaflet to V1.03 I can see map, but no markers. How can i solve this problem. Thanks in advantage

    • I would start by looking at your developer console to see if you have any errors showing up.

      When switching from http to https you’ll need to make sure that all your script links and so on use https otherwise you’ll get “mixed content” errors with some browsers.

  4. Hi Andy,
    Thank you for these scripts and the detailed explanation. My very basic knowledge of html and javascript is sufficient to get this working. On my site, http://polten.be, I’m sharing gpx tracks. I’m using the cluster plugin to show the starting point of each track on a map.

  5. Heyho,
    thanks for your great explanation!
    Sadly I am working with WordPress, where I can’t just create a website with custom html.
    Do you have any hint how to use Clustering on WordPress?
    Thank you in advance and have a wonderful day!

    • I’m using it on WordPress as well. If you are using it on a “managed” server (like wordpress.com) then I don’t know if it’s possible.

      If you are managing the site yourself, then you have to put the scripts & files in your theme directory and reference them directly. I put the JSON and the JavaScript in its own directory (“maps”) and then embed the map in a page by writing and using custom shortcodes.

  6. Hi there,
    Thanks for explanation. I want to know one thing that is it possible to save the clusters that leaflet makes in a new column in my table. for example if they are 2 locations beside each other and they clustered together in leaflet, in cluster column have 1 for each of them as cluster label?

    I need that and if there is something to save that, it would be great as I don’t like the result of my knn clustering.

    • I’m not 100% sure I understand your question. Is it that you want to use this plugin to cluster your data, then output that information to use elsewhere? i.e. use it to process your data once? (Also – won’t you need a cluster number for each level of zoom?)

      If that’s what you’re trying to do – wouldn’t it be easier to find/implement a clustering algorithm separately?

  7. Can you post a jsfiddle version of this please? I can’t get it to run on a jsfiddle myself and this looks like a great way to learn.

  8. Hello, thank you for this helpful tutorial.
    I tried to realize a map leaflet with cluster, i keep track your method,it display just the markers whithout cluster and with an error ‘ t is null’ in the file leaflet.js
    anyone has any idea for that, i need a help!!
    thnx 🙂

    • I would suggest opening it in Chrome and using the developer tools to see what’s going on. Figure out where it’s giving that error then look at the call stack and step through the code to see where it’s failing.

      Also check the versions – things may have changed since I wrote this post. This example is using Leaflet 0.7.7 and MarkerCluster v0.4.0.

  9. Hi All, I have created one blueprint map by CATileLayer as imageView on ScrollView in Objective c. According to the selected location i pin the point (CGPoint(x,y)) so i have around 1000 CGPoint. As of now i have to do cluster marker for according to the CGPoint. Is it possible to do cluster marker by leaflet ? if it’s there please comment here.

  10. I am using cluster group. But how to fix cluster expand level. Suppose default cluster group loads with continent level then click. It expand to deeper level and when third click on cluster group again it expand to country level. I want to fix three expand level of cluster group.

    I tried freezeAtZoom() but it stops the cluster group from expand even from first level..

  11. Hi
    Instead of the aggreated count as number , i want to fill the colour in that geo polygon like choropleth

    How to do that?

    Thank you

    • Diouck:

      I’m not sure I understand your question.

      You have some data which includes coordinates – are you asking how to access the coordinates within that data structure? Or are you asking how to extract the coordinates and put them in a GeoJSON file?

  12. Thank you very much for your tutorial very helpful. Can you plz tell me what wrong with my code. It only works when I have one point. When I try to loop more than one nothing is displayed.

    • I would suggest opening it in Chrome and using the developer tools to set a breakpoint on the for loop to check that point.length is returning what you think it should return. Then step through that code to see what’s not working as expected.

  13. What needs to be changed if we want to convert this example to work with Leaflet v 1.0.0 beta 0.2 ?

      • It saved my day for sure. Thank you. I stumbled into an issue and if you know off the top of your head please feel free to advise.

        I am adding a link on each of the popups and then ajax loading another page into a div when the link is clicked. Once the ajax load happens, the leaflet map becomes unresponsive. At first I thought it was due to my code, but I removed the clustering part and it works fine.

        I am attaching the code below. I am not asking you for a full fledged solution but if you have seen this behavior or have an insight, please feel free to share:

        I am attaching an event handler to each of the items with class ‘link’ like this:

        I am ajax loading a different page in the createDialog method like this:

        Thanks

  14. Hi,
    Thanks for your detailed explanation about marker clustering in openstreetmap with leaflet.
    I understood as, currently marker clustering are works based on distance, right?
    I want to cluster markers based on region, for example cluster all markers in a particular country or state.
    Can anyone help me!