CARTO Mobile SDK can dynamically cluster point data if large amounts of points need to be shown without cluttering the MapView. Clusters are formed based on the map zoom level and spatially close points are placed into the same cluster.
Clusters are usually markers which display a location of several objects, and typically indicate the number of markers within each object.
CARTO Mobile SDK has built-in cluster feature, which is highly customizable. You can define the following options in your app code:
Styling the cluster objects
Dynamically generate cluster object styles. For example, automatically display the number of objects in each cluster
Define the minimum zoom level for clusters
Set the minimum distance between objects, before it becomes a cluster
Indicate the action when clicking on marker. For example, zoom in, or expand the cluster without zooming
Tip: The cluster expand feature is useful for small clusters (containing up to four objects inside)
Depending on the device, the Mobile SDK can cluster 100,000 points in less than a second.
Implementing clustering
Clusters are generated dynamically, based on VectorDataSource data that loads the map layer. If using an API, it works as a unique layer with the ClusteredVectorLayer method, and includes the following parameters in the a hierarchal order:
Select the layer DataSource In most cases, the LocalVectorDataSource function contains all the elements to request the data. It is important that the DataSource displays all elements in a layer, and does not limit it to the current map visualization bbox (bounding box)
ClusterElementBuilder defines a single method buildClusterElement
// 1. Initialize a local vector data sourceLocalVectorDataSourcevectorDataSource1=newLocalVectorDataSource(mapView.getOptions().getBaseProjection());// 2. Create Marker objects and add them to vectorDataSource// **Note:** This depends on the _app type_ of your mobile app settings. See AdvancedMap for samples with JSON loading and random point generation// 3. Initialize a vector layer with the previous data sourceClusteredVectorLayervectorLayer1=newClusteredVectorLayer(vectorDataSource1,newMyClusterElementBuilder(this.getApplication()));vectorLayer1.setMinimumClusterDistance(20);// 4. Add the previous vector layer to the mapmapView.getLayers().add(vectorLayer1);
1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. Create overlay layer for markersvardataSource=newLocalVectorDataSource(MapView.Options.BaseProjection);// 2. Create Marker objects and add them to vectorDataSource.// **Note:** This depends on the _app type_ of your mobile app settings. See samples with JSON loading// 3. Initialize a vector layer with the previous data sourcevarlayer=newClusteredVectorLayer(dataSource,newMyClusterElementBuilder());layer.MinimumClusterDistance=20;// in pixelsMapView.Layers.Add(layer);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1. Initialize a local vector data sourceNTProjection*proj=[[mapViewgetOptions]getBaseProjection];NTLocalVectorDataSource*vectorDataSource=[[NTLocalVectorDataSourcealloc]initWithProjection:proj];// 2. Create Marker objects and add them to vectorDataSource.// **Note:** This depends on the _app type_ of your mobile app settings. See AdvancedMap for samples with JSON loading and random point generation// 3. Create element builderMyMarkerClusterElementBuilder*clusterElementBuilder=[[MyMarkerClusterElementBuilderalloc]init];// 4. Initialize a vector layer with the previous data sourceNTClusteredVectorLayer*vectorLayer=[[NTClusteredVectorLayeralloc]initWithDataSource:vectorDataSourceclusterElementBuilder:clusterElementBuilder];[[mapViewgetLayers]add:vectorLayer];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 1. Initialize a local vector data sourceletvectorDataSource1=NTLocalVectorDataSource(projection:mapView?.getOptions().getBaseProjection())// 2. Create Marker objects and add them to vectorDataSource// **Note:** This depends on the _app type_ of your mobile app settings.// See AdvancedMap for samples with JSON loading and random point generation// 3. Initialize a vector layer with the previous data sourceletbuilder=MyClusterElementBuilder(imageUrl:"marker_black.png")letvectorLayer1=NTClusteredVectorLayer(dataSource:vectorDataSource1,clusterElementBuilder:builder)vectorLayer1?.setMinimumClusterDistance(20)// 4. Add the previous vector layer to the mapmapView?.getLayers()?.add(vectorLayer1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 1. Initialize a local vector data sourcevalvectorDataSource1=LocalVectorDataSource(mapView?.options?.baseProjection)// 2. Create Marker objects and add them to vectorDataSource// **Note:** This depends on the _app type_ of your mobile app settings.// See AdvancedMap for samples with JSON loading and random point generation// 3. Initialize a vector layer with the previous data sourcevalvectorLayer1=ClusteredVectorLayer(vectorDataSource1,MyClusterElementBuilder(this.application))vectorLayer1.minimumClusterDistance=20f// 4. Add the previous vector layer to the mapmapView?.layers?.add(vectorLayer1)
Define ClusterElementBuilder
The Cluster Element Builder takes set of original markers (map objects) as input, and returns one object (or another VectorElement, such as a Point or BalloonPopup) which dynamically replaces the original marker.
Note: It is highly recommended to reuse and cache styles to reduce memory usage. For example, a marker style with a specific number is only created once. Android and iOS samples use platform-specific graphic APIs to generate the bitmap for the marker. .NET example only uses BalloonPopup, which is slower but works the same across all platforms.