Engineering

07 October, 2019

How to Cluster Markers on Flutter using Google Maps

If you’re using Google Maps to display markers on your Flutter app, I’m sure that you will eventually need to cluster those markers. You don’t want users to zoom out and see hundreds of markers spamming the map right?

António Valente

Software Engineer

How to Cluster Markers on Flutter using Google Maps - Coletiv Blog

If you’re using Google Maps to display markers on your Flutter app, I’m sure that you will eventually need to cluster those markers. You don’t want users to zoom out and see hundreds of markers spamming the map right?

Well, as I’m sure you know by now, that feature isn’t supported yet by the official Google Maps package. Check this issue to know more.

Rest assured though because I’ve got a solution that might work for you.

We have a solution for you! We have a solution for you!

Fluster Package Comes to the Rescue

In your search for solutions, you probably bumped into the Fluster package. This package uses a Dart port of supercluster and works really well, but how do you use it on your Flutter project?

The readme is very brief, doesn’t explain much and the example isn’t even a Flutter project. This makes the package very easy to overlook unless you find this demo project by the package author, but even with this code, you will struggle to understand how to use it in your project. At least I did. Again, there are no proper readme instructions and the code can be a bit overwhelming at first.

In this article, I will break down the code and explain it step by step so you can understand and implement a similar solution in your project.

Implementing Fluster

1. Extending the Clusterable class

Fluster can only handle markers that conform to the Clusterable abstract class so this is a good place to start.

import 'package:fluster/fluster.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:meta/meta.dart'; class MapMarker extends Clusterable { final String id; final LatLng position; final BitmapDescriptor icon; MapMarker({ @required this.id, @required this.position, @required this.icon, isCluster = false, clusterId, pointsSize, childMarkerId, }) : super( markerId: id, latitude: position.latitude, longitude: position.longitude, isCluster: isCluster, clusterId: clusterId, pointsSize: pointsSize, childMarkerId: childMarkerId, ); Marker toMarker() => Marker( markerId: MarkerId(id), position: LatLng( position.latitude, position.longitude, ), icon: icon, ); }

Here is my implementation. You can see it on Github here. Notice how I’ve added the toMarkert() method. This method will come in handy later on, to convert our list of MapMarkers to a list of Markers so our GoogleMap widget doesn’t complain.

Note that you can add more arguments to the class depending on your use case. Like an onTap() callback or a Marker InfoWindow.

2. Create the List of Markers to be Displayed

import 'package:flutter_google_maps_clusters/helpers/map_marker.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; final List<MapMarker> markers = []; final List<LatLng> markerLocations = [ LatLng(41.147125, -8.611249), LatLng(41.145599, -8.610691), ... ]; for (LatLng markerLocation in _markerLocations) { markers.add( MapMarker( id: markerLocations.indexOf(markerLocation).toString(), position: markerLocation, icon: markerImage, ), ); }

You should have a list of locations where you want to place the markers. Create a MapMarker for every location.

3. Init Fluster

import 'package:fluster/fluster.dart'; import 'package:flutter_google_maps_clusters/helpers/map_marker.dart'; final Fluster<MapMarker> fluster = Fluster<MapMarker>( minZoom: minZoom, // The min zoom at clusters will show maxZoom: maxZoom, // The max zoom at clusters will show radius: 150, // Cluster radius in pixels extent: 2048, // Tile extent. Radius is calculated with it. nodeSize: 64, // Size of the KD-tree leaf node. points: markers, // The list of markers created before createCluster: ( // Create cluster marker BaseCluster cluster, double lng, double lat, ) => MapMarker( id: cluster.id.toString(), position: LatLng(lat, lng), icon: clusterImage, isCluster: cluster.isCluster, clusterId: cluster.id, pointsSize: cluster.pointsSize, childMarkerId: cluster.childMarkerId, ), );

Here, you’re creating your Fluster instance. It will handle all the logic of updating the markers and clusters you need to show in your map for a given zoom level. For more information about the parameters used, check out the Fluster source code or the supercluster options.

4. Get Cluster Markers

import 'package:fluster/fluster.dart'; import 'package:flutter_google_maps_clusters/helpers/map_marker.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; final List<Marker> googleMarkers = fluster .clusters([-180, -85, 180, 85], currentZoom) .map((cluster) => cluster.toMarker()) .toList()

Now you’ll see that handy toMarker() method coming to action. We’re telling fluster to get the cluster markers within the giving bounding box of [westLng, southLat, eastLng, northLat] for the current zoom level and converting them to Google Maps Markers. Now we can use that list to show the markers on the map.

5. Show the Map with Markers

import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; @override Widget build(BuildContext context) { return Scaffold( body: GoogleMap( initialCameraPosition: CameraPosition( target: LatLng(41.143029, -8.611274), zoom: currentZoom, ), markers: googleMarkers.toSet(), onMapCreated: (controller) { // You can init Fluster here }, onCameraMove: (position) { // Update the markers for the updated position.zoom ), ), ); }

In the build(context) method of your page, you should create your Google Map widget and pass the markers created by fluster and voilà! You will have clusters showing in your map. 👏 👏 👏

You can use the onMapCreated() to know when the map is ready to show your markers. Also, make sure to update the markers with the updated zoom level on the onCameraMove() by calling setState() or using your favorite state management system, so Fluster knows if it needs to cluster or uncluster some markers.

Marker Clustering Working on Google MapsMarker Clustering Working on Google Maps

Now you have all the code needed to implement marker clustering on your GoogleMap widget. Hope you‘ve found this article useful and understood how everything works.

Be sure to check the example project at the Coletiv Github account to see the rest of the code needed to implement clusters on Google Maps.

Don’t forget to add your Google Maps API key to the project if you want to see it working. Just add it here and here.

Also, if you want to try some alternatives to handle marker clusters check out Flutter Map and Flutter Map Marker Cluster packages.

Flutter

Software Development

Google Maps

Clustering

Marker

Join our newsletter

Be part of our community and stay up to date with the latest blog posts.

Subscribe

Join our newsletter

Be part of our community and stay up to date with the latest blog posts.

Subscribe

You might also like...

Go back to blogNext
How to support a list of uploads as input with Absinthe GraphQL

Engineering

26 July, 2022

How to support a list of uploads as input with Absinthe GraphQL

As you might guess, in our day-to-day, we write GraphQL queries and mutations for Phoenix applications using Absinthe to be able to create, read, update and delete records.

Nuno Marinho

Software Engineer

Flutter Navigator 2.0 Made Easy with Auto Router - Coletiv Blog

Engineering

04 January, 2022

Flutter Navigator 2.0 Made Easy with Auto Router

If you are a Flutter developer you might have heard about or even tried the “new” way of navigating with Navigator 2.0, which might be one of the most controversial APIs I have seen.

António Valente

Software Engineer

Enabling PostgreSQL cron jobs on AWS RDS - Coletiv Blog

Engineering

04 November, 2021

Enabling PostgreSQL cron jobs on AWS RDS

A database cron job is a process for scheduling a procedure or command on your database to automate repetitive tasks. By default, cron jobs are disabled on PostgreSQL instances. Here is how you can enable them on Amazon Web Services (AWS) RDS console.

Nuno Marinho

Software Engineer

Go back to blogNext