Marker Clustering
This example demonstrates how to render thousands of markers loaded from a bundled GeoJSON file and cluster them natively using Maps SDK for Flutter. At low zoom the markers group into count "pill" bubbles; as you zoom in the clusters break apart into per-type coloured pins. Tapping a cluster zooms in to split it, and tapping a pin opens an info sheet.
Dependencies
This example requires Maps SDK for Flutter 3.1.10 or newer. Add it to the dependencies section of your pubspec.yaml:
dependencies:
magiclane_maps_flutter: ^3.1.10
Saving Assets
Before running the app, ensure that you save the campsite data and pin icons into the assets directory:
assets/campsites.geojson— the marker source dataassets/pin_bookable.png— red pin, bookable campsitesassets/pin_non_bookable.png— green pin, info-only campsites
Update your pubspec.yaml file to include these assets:
flutter:
assets:
- assets/campsites.geojson
- assets/pin_bookable.png
- assets/pin_non_bookable.png
How it works
The map uses two overlapping SDK-drawn marker collections. A marker that carries its own per-marker render settings suppresses the SDK's cluster count label, so the count and the coloured pins cannot come from a single collection:
- Cluster layer — one point-marker per campsite with collection-level settings only. The SDK groups the points into density "pill" bubbles and paints the count on them; loose points draw a transparent image.
- Detail layer — one coloured green/red pin per campsite added through the SDK's optimised bulk
addList(...)path. Its group images are transparent, so it shows nothing while clustered and only its pins once the clusters split.
Both collections group at the same zoom level, so a pill never sits on top of a pin.
UI and Map Integration
This code sets up the map screen, enables the (invisible) cursor so a tap can select a marker, and centers the camera on the initial view.
Loading and parsing the GeoJSON
The bundled GeoJSON is read from assets and decoded on a background isolate (compute) so the multi-MB parse never janks the UI thread.
The cluster layer (count "pill" bubbles)
The first collection holds one point-marker per campsite with collection-level settings only. buildPointsGroupConfig plus the density images and count thresholds make the SDK group loose points into count-bearing pills. Note that labelGroupTextColor defaults to transparent — it must be set opaque or the count is invisible.
The detail layer (coloured pins)
The second collection carries one green/red pin per campsite through the optimised bulk addList(...) path. Its group images are transparent, so while clustered it shows nothing and the cluster layer's pills show instead; once the clusters split its pins appear.
As you zoom in, the clusters break apart: smaller count pills give way to the individual green (info-only) and red (bookable) pins.
Handling taps
On touch, the cursor position is set (awaited) before reading the selection. A coordinateGroup match means a cluster was tapped — zoom in toward the tap to break it apart. Otherwise a single campsite was tapped — center on it and show its info sheet.


