Marker auf einer Leaflet Karte nach Bundesländern clustern

Wie ich in meinem letzten Blogbeitrag erwähnt habe, gibt es noch ein kleines Bonus-Thema in der Serie zu individuellen Karten. Im vorherigen Beitrag haben wir eine Karte mit Leaflet in JavaScript erstellt. Darauf wurden die Landeshauptstädte visualisiert. Zwei davon liegen recht habe zusammen und man kann sie nur schwer anklicken. Aber wie sähe eine Karte mit allen Großstädten (ca. 100.00 und größer) aus:

© ammap.com | SVG map of Germany (low detail), verwendet mit Leaflet, verändert durch Bernhard Kau, CC BY-NC 4.0

Vor allem in Nordrhein-Westfalen ist es nun unmöglich alle Marker zu sehen, zu hovern und anzuklicken. Aber da wir Leaflet verwenden, gibt es hierfür eine Lösung:

Verwendung von Marker-Clustern

Es gibt eine Erweiterung von Leaflet mit dem Namen Leaflet.markercluster, die wir verwenden können, um die Marker zu clustern. Hierzu müssen wir zuerst ein paar weiter CSS und JavaScript-Dateien einbinden:

<link rel="stylesheet"
      href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css"
      integrity="sha256-YU3qCpj/P06tdPBJGPax0bm6Q1wltfwjsho5TR4+TYc="
      crossorigin=""/>
<link rel="stylesheet"
      href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.Default.css"
      integrity="sha256-YSWCMtmNZNwqex4CEw1nQhvFub2lmU7vcCKP+XVwwXA="
      crossorigin=""/>

<script src="https://unpkg.com/leaflet.markercluster@1.5.3/dist/leaflet.markercluster.js"
        integrity="sha256-Hk4dIpcqOSb0hZjgyvFOP+cEmDXUKKNE/tT542ZbNQg="
        crossorigin=""></script>

Jetzt können wir eine markerClusterGroup erstellen und die Marker hinzufügen. Am Ende müssen wir die Gruppe dann noch zur Karte hinzufügen:

const markers = L.markerClusterGroup();

cities.map( city => {
    let marker = L.marker( [ city.lat, city.lng ], { title: city.name } );
    marker.on( 'click', function () {
        window.location = city.url;
    } );
    markers.addLayer( marker );
} );

markers.addTo( map );

Standardmäßig werden Marker in einem max. Radius von 80 Pixeln zu einem Cluster hinzugefügt. Für die Deutschlandkarte würde das dann wie folgt aussehen:

© ammap.com | SVG map of Germany (low detail), verwendet mit Leaflet, verändert durch Bernhard Kau, CC BY-NC 4.0

Das mag zwar die effektivste Clusterung sein, aber es sieht nicht wirklich schön aus, da wir in manchen Bundesländern mehrere Cluster haben, in anderen aber keine. Daher möchte ich ein Cluster pro Bundesland haben.

Marker nach Bundesländern clustern

Wir können mehrere markerClusterGroup Objekte zu einer Karte hinzufügen. Wir erstellen also 16 Gruppen für die 16 Bundesländer und fügen dann die Marker der jeweils korrekten Gruppe hinzu. Sehen wir uns zunächst einmal den Code dafür an:

const stateMarkers = {};

// Get a unique list of all states from the cities array.
[ ...new Set( cities.map( city => city.state ) ) ].map( state => {
    // Create a markerClusterGroup per state.
    stateMarkers[state] = L.markerClusterGroup( {
        maxClusterRadius: 1000,
        spiderfyOnMaxZoom: false,
        showCoverageOnHover: false,
        disableClusteringAtZoom: 8,
    } );
} );

// Create city markers and add them to the correct markerClusterGroup.
cities.map( city => {
    let marker = L.marker( [ city.lat, city.lng ], { title: city.name } );
    marker.on( 'click', function () {
        window.location = city.url;
    } );
    stateMarkers[city.state].addLayer( marker );
} );

// Add all markerClusterGroups to the map.
Object.keys( stateMarkers ).map( state => {
    stateMarkers[state].addTo( map );
} );

Zuerst einmal erstellen wir ein Objekt für die Gruppen aller Bundesländer. Dann verwenden wir etwas JavaScript-Magie, um eine Liste mit allen Bundesländernamen aus dem cities Objekt zu bekommen und erstellen dann jeweils eine Gruppe. Für die Cluster-Gruppen setzen wir den maxClusterRadius auf 100 Pixel, da unsere Karte kleiner als 1000 Pixel ist und somit jede Cluster-Gruppe mindestens so groß ist, wie jedes Bundesland. Wir deaktivieren dann noch zwei Optionen, die wir nicht brauchen und begrenzen das Zoom-Level auf 8. Bei diesem Zoom-Level werden dann alle Cluster aufgelöst, sobald ein Cluster angeklickt wird.

Nachdem wir unsere Gruppen haben, erstellen wir die Marker und fügen sie den Gruppen hinzu. Am Ende fügen wir dann noch alle Gruppen zu Karte hinzu. Damit erhalten wir dann das folgende Ergebnis (Screenshot):

© ammap.com | SVG map of Germany (low detail), verwendet mit Leaflet, verändert durch Bernhard Kau, CC BY-NC 4.0

Manche Bundesländer haben nur einen Marker. In diesem Fall werden sie einfach angezeigt. Alle andern haben Cluster. Für Nordrhein-Westfalen haben wir ein Cluster mit 30 Markern. Klicken wir darauf, erhalten wir die folgende gezoomte Ansicht (Screenshot):

© ammap.com | SVG map of Germany (low detail), verwendet mit Leaflet, verändert durch Bernhard Kau, gezoomt, CC BY-NC 4.0

Falls eure Karte mehr Marker hat oder diese näher zusammen sind, müsste ihr die Optionen für die Cluster-Gruppen eventuell etwas anders einstellen. Für dieses Beispiel würde ich sagen, dass sie nun anklickbar sind.

Fazit

Das sollte der letzte Beitrag in meiner kleinen Karten-Reihe gewesen sein. Es gibt sicher noch dutzende Themen rund um Karten im Allgemeinen oder zu Leaflet, aber dazu gibt es andere Blogs oder Dokumentationen.

Ich hoffe, dass ihr nun auch Lust habt, mal eigene (dynamische) Karten zu erstellen. Und auch die Beispiele aus diesem Beitrag findet ihr wieder in einer einzelnen HTML-Datei in einem neuen Branch auf GitHub.

Falls ihr noch weiter Themen habt, die ich behandeln soll, hiterlasst bitte einen Kommentar.

Veröffentlicht von

Bernhard ist fest angestellter Webentwickler, entwickelt in seiner Freizeit Plugins, schreibt in seinem Blog über WordPress und andere Themen, treibt sich gerne bei den WP Meetups in Berlin und Potsdam herum und läuft nach Feierabend den ein oder anderen Halbmarathon.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert