Clustering annotations with Mapbox
I did some research on this not too long ago and it didn't seem to be possible on iOS. Here is the suggestion on github that is still open. Here is another issue about how it wasn't mentioned in the documentation but has since been added.
Does anyone have a working example of Mapbox clustering with MGLAnnotations rather than geoJSON source file?
Given a Style
let style: MGLStyle
1) Build/Get your [MGLPointFeature]
2) Build a MGLShapeSource
let source = MGLShapeSource(identifier: "YOUR_IDENTIFIER_A", features: YOUR_ MGLPointFeature_ARRAY, options: [.clustered: true, .clusterRadius: YOUR_WIDTH])
style.addSource(source)
3) Build a style for the marker when it's not clustered
let markerLayer = MGLSymbolStyleLayer(identifier: "YOUR_IDENTIFIER_B", source: source)
markerLayer.iconImageName = NSExpression(forConstantValue: "MARKER_IDENTIFIER")
markerLayer.predicate = NSPredicate(format: "cluster != YES")
style.setImage(UIImage(named: "MARKER_IMAGE")!, forName: "MARKER_IDENTIFIER")
4) Build a style for the cluster
let clusterLayer = MGLSymbolStyleLayer(identifier: "YOUR_IDENTIFIER_C", source: source)
clusterLayer.textColor = NSExpression(forConstantValue: UIColor.white)
clusterLayer.textFontSize = NSExpression(forConstantValue: NSNumber(value: Double(YOUR_WIDTH) / 2.5))
clusterLayer.iconAllowsOverlap = NSExpression(forConstantValue: true)
clusterLayer.textOffset = NSExpression(forConstantValue: CGVector(dx: 0, dy: -0.2))
clusterLayer.predicate = NSPredicate(format: "cluster == YES")
style.setImage(UIImage(named: "CLUSTER_IMAGE")!, forName: "CLUSTER_IDENTIFIER")
5) You can use Stops features. This will let you change cluster image based on clustering count change.
let stops = [
10: NSExpression(forConstantValue: "CLUSTER_IMAGE"),
50: NSExpression(forConstantValue: "ANOTHER_CLUSTER_IMAGE")
]
6) Use expressions to set each cluster's image based on defined stops and display the point count over the corresponding image
let defaultShape = NSExpression(forConstantValue: "CLUSTER_IDENTIFIER")
clusterLayer.iconImageName = NSExpression(format: "mgl_step:from:stops:(point_count, %@, %@)", defaultShape, stops)
clusterLayer.text = NSExpression(format: "CAST(point_count, 'NSString')")
7) Add layers to the Style
style.addLayer(markerLayer)
style.addLayer(clusterLayer)