Cluster

repository·master·Indexed 23 days ago

https://github.com/efremidze/cluster

An efficient iOS library for map annotation clustering using the QuadTree algorithm. It provides the ClusterManager class to aggregate MKAnnotation objects into single cluster annotations, improving map readability and performance. Features include customizable ClusterAnnotationView appearances, support for ClusterAnnotationStyle, and a ClusterManagerDelegate for controlling clustering logic and cell sizing.

Tokens
1.6K
Snippets
7
Records
9
Agent score
30%

What's inside Cluster

  1. Install Cluster via CocoaPods or Carthage

    master

    Cluster can be integrated into your iOS project using either CocoaPods or Carthage.

    CocoaPods Add the following to your Podfile:

    pod "Cluster"

    Carthage Add the following to your Cartfile:

    github "efremidze/Cluster"
    pod "Cluster"
    # or
    github "efremidze/Cluster"
  2. Configure annotation views for clusters

    master

    To display clusters on the map, you must implement the mapView(_:viewFor:) delegate method. When the annotation is a ClusterAnnotation, return an instance of ClusterAnnotationView (or a subclass).

    For standard pins, return a regular MKAnnotationView (like MKPinAnnotationView).

    extension ViewController: MKMapViewDelegate {
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            if let annotation = annotation as? ClusterAnnotation {
                return CountClusterAnnotationView(annotation: annotation, reuseIdentifier: "cluster")
            } else {
                return MKPinAnnotationView(annotation: annotation, reuseIdentifier: "pin")
            }
        }
    }
  3. Remove and reload annotations

    master

    To remove an annotation, call manager.remove(annotation:).

    Important: Annotations are not immediately removed from the map view. You must call reload(mapView:completionHandler:) to update the display. It is recommended to call reload() whenever you add or remove annotations, and specifically when the map region changes.

    // Remove
    manager.remove(annotation)
    
    // Reload (typically in mapView(_:regionDidChangeAnimated:))
    func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
        clusterManager.reload(mapView: mapView) { finished in
            // handle completion
        }
    }
  4. Customize ClusterAnnotationView appearance

    master

    You can customize the look of clusters by subclassing ClusterAnnotationView and overriding the configure() method. This is useful for modifying properties like countLabel, layer.borderColor, or layer.cornerRadius.

    class CountClusterAnnotationView: ClusterAnnotationView {
        override func configure() {
            super.configure()
    
            self.layer.cornerRadius = self.frame.width / 2
            self.layer.masksToBounds = true
            self.layer.borderColor = UIColor.white.cgColor
            self.layer.borderWidth = 1.5
        }
    }
  5. Apply custom styles to annotations

    master

    You can use the ClusterAnnotationStyle enum to define how an annotation appears. Supported styles include:

    • .color(UIColor, radius: CGFloat): Displays the annotation as a circle.
    • .image(UIImage?): Displays the annotation as an image.

    When using styles, you must return a StyledClusterAnnotationView in your mapView(_:viewFor:) implementation.

    let annotation = Annotation(coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
    annotation.style = .color(color, radius: 25)
    manager.add(annotation)
    
    // In mapView(_:viewFor:)
    if let annotation = annotation as? ClusterAnnotation {
        return StyledClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, style: style)
    }
  6. Implement ClusterManagerDelegate

    master

    The ClusterManagerDelegate protocol allows you to control clustering logic and cell sizing via two methods:

    • cellSize(for zoomLevel: Double) -> Double?: Returns the size of each cell on the grid for a specific zoom level.
    • shouldClusterAnnotation(_ annotation: MKAnnotation) -> Bool: Returns a boolean indicating whether a specific annotation should be clustered.
  7. Add annotations to the cluster

    master

    To add annotations, ensure your object conforms to the MKAnnotation protocol. Use the add(annotation:) method on your ClusterManager instance.

    let annotation = Annotation(coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
    manager.add(annotation)
  8. Use ClusterManager to manage annotations

    master

    The ClusterManager class is the core component used to generate, manage, and display annotation clusters using a QuadTree method.

    To start, initialize an instance of ClusterManager.

    let clusterManager = ClusterManager()
  9. Configure ClusterManager properties

    master

    The ClusterManager provides several properties to fine-tune clustering behavior:

    PropertyDescription
    zoomLevelThe current zoom level of the visible map region.
    maxZoomLevelThe maximum zoom level before disabling clustering.
    minCountForClusteringThe minimum number of annotations required to form a cluster (default: 2).
    shouldRemoveInvisibleAnnotationsWhether to remove invisible annotations (default: true).
    shouldDistributeAnnotationsOnSameCoordinateWhether to arrange annotations in a circle if they share a coordinate (default: true).
    distanceFromContestedLocationDistance in meters for annotations with the same coordinate (default: 3).
    clusterPositionThe position of the cluster annotation (default: .nearCenter).