import GoogleMaps
import UIKit
import GoogleMapsUtils
/// Point of Interest Item which implements the GMUClusterItem protocol.
class POIItem: NSObject, GMUClusterItem {
var position: CLLocationCoordinate2D
var name: String!
init(position: CLLocationCoordinate2D, name: String) {
self.position = position
self.name = name
}
}
let kClusterItemCount = 10000
let kCameraLatitude = -33.8
let kCameraLongitude = 151.2
class ClusteringViewController: UIViewController, GMSMapViewDelegate, GMUClusterRendererDelegate {
private var mapView: GMSMapView!
private var clusterManager: GMUClusterManager!
override func loadView() {
let camera = GMSCameraPosition.camera(withLatitude: kCameraLatitude,
longitude: kCameraLongitude, zoom: 10)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
self.view = mapView
}
override func viewDidLoad() {
super.viewDidLoad()
// Set up the cluster manager with default icon generator and renderer.
let iconGenerator = GMUDefaultClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
// Register self to listen to GMSMapViewDelegate events.
clusterManager.setMapDelegate(self)
// Generate and add random items to the cluster manager.
generateClusterItems()
// Call cluster() after items have been added to perform the clustering and rendering on map.
clusterManager.cluster()
}
// MARK: - GMUMapViewDelegate
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
mapView.animate(toLocation: marker.position)
if let _ = marker.userData as? GMUCluster {
mapView.animate(toZoom: mapView.camera.zoom + 1)
NSLog("Did tap cluster")
return true
}
NSLog("Did tap marker")
return false
}
// MARK: - Private
/// Randomly generates cluster items within some extent of the camera and adds them to the
/// cluster manager.
private func generateClusterItems() {
let extent = 0.2
for _ in 1...kClusterItemCount {
let lat = kCameraLatitude + extent * randomScale()
let lng = kCameraLongitude + extent * randomScale()
let position = CLLocationCoordinate2D(latitude: lat, longitude: lng)
let marker = GMSMarker(position: position)
clusterManager.add(marker)
}
}
/// Returns a random value between -1.0 and 1.0.
private func randomScale() -> Double {
return Double(arc4random()) / Double(UINT32_MAX) * 2.0 - 1.0
}
func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
if let cluster = marker.userData as? GMUCluster {
print("Current cluster size: \(cluster.count)")
marker.icon = createClusterIcon(size: Int(cluster.count))
}
}
func createClusterIcon(size: Int) -> UIImage {
let clusterSize: CGFloat = 40
let renderer = UIGraphicsImageRenderer(size: CGSize(width: clusterSize, height: clusterSize))
let image = renderer.image { context in
UIColor(red: 0.13, green: 0.59, blue: 0.95, alpha: 1.0).setFill()
UIBezierPath(arcCenter: CGPoint(x: clusterSize / 2, y: clusterSize / 2), radius: clusterSize / 2, startAngle: 0, endAngle: .pi * 2, clockwise: true).fill()
// Draw cluster count text
let text = String(size)
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.boldSystemFont(ofSize: 16),
.foregroundColor: UIColor.white
]
let textSize = text.size(withAttributes: attributes)
let textPoint = CGPoint(
x: (clusterSize - textSize.width) / 2,
y: (clusterSize - textSize.height) / 2
)
text.draw(at: textPoint, withAttributes: attributes)
}
return image
}
}
Cluster with icon blue circle and cluster size text to display. Print function run when icon display
Cluster still use the default cluster icon.
Environment details
Steps to reproduce
Code example
Expect Result
Cluster with icon blue circle and cluster size text to display. Print function run when icon display
Actual Result
Cluster still use the default cluster icon.