How to implement GMUClusterRenderer in Swift
I found a clean solution for clustered markers, on Swift 4, to use a custom image for the cluster with the number of cluster inside:
class MapClusterIconGenerator: GMUDefaultClusterIconGenerator {
override func icon(forSize size: UInt) -> UIImage {
let image = textToImage(drawText: String(size) as NSString,
inImage: UIImage(named: "cluster")!,
font: UIFont.systemFont(ofSize: 12))
return image
}
private func textToImage(drawText text: NSString, inImage image: UIImage, font: UIFont) -> UIImage {
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
let textStyle = NSMutableParagraphStyle()
textStyle.alignment = NSTextAlignment.center
let textColor = UIColor.black
let attributes=[
NSAttributedStringKey.font: font,
NSAttributedStringKey.paragraphStyle: textStyle,
NSAttributedStringKey.foregroundColor: textColor]
// vertically center (depending on font)
let textH = font.lineHeight
let textY = (image.size.height-textH)/2
let textRect = CGRect(x: 0, y: textY, width: image.size.width, height: textH)
text.draw(in: textRect.integral, withAttributes: attributes)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result!
}
}
Than the setup for the cluster manager:
private func setupClustering() {
guard let mapView = self.mapView else { return }
let iconGenerator = MapClusterIconGenerator()
let renderer = MapClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
}
I also used a custom cluster renderer MapClusterRenderer
.
Customize the marker on google map with clusters
After creating your GMUDefaultClusterRenderer
set its delegate I used the view controller I was working in, and then implement the GMUClusterRendererDelegate
let iconGenerator = GMUDefaultClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
renderer.delegate = self
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
After that you implement the func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker)
from the protocol. This method gives you access to the marker and the data enclosed in the marker.
Use an If let statement to access the data and give the marker the iconView you want if let markerData = marker.userData
How to clustered markers from Firebase in GoogleMaps for iOS
Firstly loadMarker()
should be called after the clusterManager is initialized i.e
clusterManager = GMUClusterManager(map: maMap, algorithm: algorithm, renderer: renderer)
then
clusterManager.cluster()
clusterManager.setDelegate(self, mapDelegate: self)
should be placed in loadMarker()
after for loop ends.
Your viewcontroller should conform to this protocol GMUClusterManagerDelegate
then add these 2 methods in viewcontroller.
func renderer(_ renderer: GMUClusterRenderer, markerFor object: Any) -> GMSMarker? {
let marker = GMSMarker()
if let model = object as? MarkerModel {
// set image view for gmsmarker
}
return marker
}
func clusterManager(_ clusterManager: GMUClusterManager, didTap cluster: GMUCluster) -> Bool {
let newCamera = GMSCameraPosition.camera(withTarget: cluster.position, zoom: mapView.camera.zoom + 1)
let update = GMSCameraUpdate.setCamera(newCamera)
mapView.moveCamera(update)
return false
}
Try this and let me know if this works else we will try something else.
How to change the cluster color of google map In Swift 4
I found an answer with a perfect solution.
@Andr3a88 Answer :
How to implement GMUClusterRenderer in Swift
The correct answer was to create the image rather than draw a circle in the script.
In the above script could also change the text.
The number of questions proves that many people like me are experiencing errors.
So I will leave a few questions to help you find a more complete solution.
How to customize default pin marker using Google Cluster Manager?
marker
has a property iconView
which is a UIView. Since it's a UIView you can customize however you want.
func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
marker.iconView = MyView()
}
Changing google maps POIItem markers
Here is the Google Documentation link: Customizing Marker Clusters
SO answer here in SWIFT: Its not pretty but apprently works.
How to implement GMUClusterRenderer in Swift
For other basic markers:
Documentation at Google for basic markers here is the link:
change the marker color
marker.icon = GMSMarker.markerImage(with: .black)
Very slow scrolling/zooming experience with GMUClusterRenderer (Google Maps Clustering) on iOS
I was facing the same issue. After debugging a lot and checking google's code even, i come to the conclusion that, issue was from GMUDefaultClusterIconGenerator
. This class is creating images at runtime for given cluster size that you are displaying. So, when you zoom in or zoom out the map, the cluster size is going to update, and this class creates new image for new number(Even it keep images cached, if same number get repeated).
So, the solution that i found is to use buckets
. You will get surprised by seeing this new term. Let me explain the bucket concept by giving simple example.
suppose you kept bucket sizes as 10, 20, 50, 100, 200, 500, 1000.
- Now, if your cluster is 3, then it will show 3.
- If cluster size = 8, show = 8.
- If cluster size = 16, show = 10+.
- If cluster size = 22, show = 20+.
- If cluster size = 48, show = 20+.
- If cluster size = 91, show = 50+.
- If cluster size = 177, show = 100+.
- If cluster size = 502, show = 500+.
- If cluster size = 1200004, show = 1000+.
Now here, for any cluster size, the marker images that are going to be rendered will be from 1, 2, 3, 4, 5, 6, 7, 8, 9, 10+, 20+, 50+, 100+, 200+, 500+, 1000+. As it caches the images, so this images is going to be reused. So, the time+cpu that it was using for creating new images is lowered(only few images required to be created).
You must have got the idea, about buckets now. As, if cluster is having very small number, then cluster size matters, but if increases, then bucket size is enough to get idea about cluster size.
Now, question is how to achieve this.
Actually, GMUDefaultClusterIconGenerator
class has already this functionality implemented, you just need to change its initialisation to this:
let iconGenerator = GMUDefaultClusterIconGenerator(buckets: [ 10, 20, 50, 100, 200, 500, 1000])
GMUDefaultClusterIconGenerator
class have other init methods, by using which you can give different background colors to different buckets, different background images to to different buckets and many more.
Let me know, if any further help required.
Related Topics
iOS - Using Storyboard and Autolayout to Center the Uiscrollview
Best Method to Store Data for an iOS App
Cgcontextsetfillcolorwithcolor: Invalid Context 0X0
How to Add Firebase to Today Extension iOS
Odd Property Declaration Syntax Containing Angular Brackets <>
iOS Facebook Sdk 3.1 Retrieve Friend Birthday Returning Null
Avplayer Uitapgesturerecognizer Not Working
Avassetresourceloaderdelegate Methods Not Working on Device
Bypass Code Signing with Xcode 6
How to Convert Image into Binary Format in iOS
How to Find Out the Objective-C Generics Type
How to Create a Uiimage with Uibezierpath
A Lighter Way of Discovering Text Writing Direction
How to Remove Black Edge on Uiimageview with Rounded Corners and a Border Width