How to provide marker clustering on the Leaflet map in the Angular project 🗺📌

Showing multiple locations on a single map isn’t easy. Both from visual and performance point of view.

But fortunately, there’s a solution to this problem, called marker clustering. Basically, it’s about gathering points together in groups called clusters. Their size depends on current map zoom settings. It helps a lot when it comes to navigation through the map.

In this text, I’m going to show you how you can achieve it in your Angular project using the Leaflet map with Leaflet.markercluster library.

Let’s use the existing Leaflet map integration which was described on this blog before. Take a look at this text.

First steps

We’re going to use ng-leaflet-markercluster which is the extension to the Leaflet package which was used in the previously mentioned text.

Installation

Let’s start with the clustering package and dependencies installation.

npm install leaflet.markercluster @asymmetrik/ngx-leaflet-markercluster

Additionally, the TypeScript typings package can be installed too:

npm install @types/leaflet.markercluster

The library needs its own assets, so let’s jump into angular.json file and add the following lines into the styles:

"./node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css"

So the final result will look more or less like this:

       "styles": [
              ...
              "./node_modules/leaflet/dist/leaflet.css",
              "./node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css"
            ],

Module import

The ngx-leaflet-markercluster provides the Angular module (LeafletMarkerClusterModule). The last step is about importing it.

Add the module name (and import it) in the AppModule (or any other module you’d like to import the clustering) imports array:

  imports: [
    LeafletMarkerClusterModule
  ]

When it comes to the installation and preparation we’re ready to go. Pretty straightforward, isn’t it?

Let’s cluster it together 🗺

Finally, it’s time to use it and test if the actual clustering happens.

Add [leafletMarkerCluster] property into your map code in your template:

    <div id="map"
         leaflet
         [leafletOptions]="mapOptions"
         (leafletMapReady)="onMapReady($event)"
         [leafletMarkerCluster]="markerClusterData"
    >

Declare the necessary properties in the component code, the simplified component code will look like this:

import * as L from 'leaflet';

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.scss']
})
export class MapComponent implements OnInit {
...

  markerClusterGroup: L.MarkerClusterGroup;
  markerClusterData = [];

  constructor () {
  }

  ngOnInit () {
    this.markerClusterGroup = L.markerClusterGroup({removeOutsideVisibleBounds: true});
  }
map.component.ts

Now, in the code where the markers are added to layers you can use addLayer or addLayers method of markerClusterGroup object.

Remember, that you have to add it to the map (with addTo method) at the end of the day.

In the simplest case, it could look like this:


private createMarker() {
    const mapIcon = this.getDefaultIcon();
    const coordinates = latLng([this.mapPoint.latitude, this.mapPoint.longitude]);
    this.lastLayer = marker(coordinates).setIcon(mapIcon);
    this.markerClusterGroup.addLayer(this.lastLayer)
    }

private getDefaultIcon() {
    return icon({
      iconSize: [25, 41],
      iconAnchor: [13, 41],
      iconUrl: 'assets/marker-icon.png'
    });
  
private addLayersToMap() {
	this.markerClusterGroup.addTo(this.map);
}

Let’s assume the createMarker is called in the for loop and we use addLayersToMap to finally add the clustered layers into the map.

The latLng, marker, icon came all from the Leaflet. Take a look at this import statement:

import {icon, latLng, marker} from 'leaflet';

Of course, there’s no need to add each marker into the cluster, you can group them into one layer and then add it to the map. It would be useful especially when you’re going to toggle the layers on the map or to switch them (with built-in layers control for example).

Here’s what I achieved using the data from this demo example:

Further improvements

If you need more sophisticated features or customization, take a look into the available options described in docs.

What’s worth mentioning is the fact that the MarkerClusterGroup class extends the FeatureGroup so it has all of the handy methods like clearLayers() or removeLayers().

Conclusion

That’s it. As you can see, providing the marker clustering for your Leaflet map is not a big problem but it can significantly improve your map user experience and performance.

Try it yourself and let me know how it went 😀

Resources

Leave a Reply

Your email address will not be published. Required fields are marked *