Reputation: 4951
I have a grouped pin that I want to zoom in on. Of course I know the coords of the pin, and have it's view rect. I just want to zoom the map to just the right region so that the cluster fully expands showing all pins (plus a bit of padding). What's a good way of doing this?
Sidenote:
In my setup the cluster pin will automatically be expanded into individual pins when the zoom level increases so I'm good there. What I need to know is how to set the MapView to a new region based on the frame and coords of the cluster pin.
Upvotes: 9
Views: 2306
Reputation: 251
You can use:
mapView.showAnnotations(groupedAnnotations, animated: true)
This method will zoom in and position the map automatically so the annotations are all visible.
Upvotes: 6
Reputation: 386
When user taps the cluster pin you'll have a callback to
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView)
Now you just need to cast your MKAnnotationView
to MKClusterAnnotation
, then you get access to the collection of its member pins:
if let clustered = view.annotation as? MKClusterAnnotation {
clustered.memberAnnotations.forEach { (annotation) in
// Calculate region boundaries
}
}
Full solution with Nick's calculations:
if let clustered = view.annotation as? MKClusterAnnotation {
var minLat = CLLocationDegrees(exactly: 90)!
var maxLat = CLLocationDegrees(exactly: -90)!
var minLong = CLLocationDegrees(exactly: 180)!
var maxLong = CLLocationDegrees(exactly: -180)!
clustered.memberAnnotations.forEach { (annotation) in
let coordinate = annotation.coordinate
minLat = min(minLat, coordinate.latitude)
maxLat = max(maxLat, coordinate.latitude)
minLong = min(minLong, coordinate.longitude)
maxLong = max(maxLong, coordinate.longitude)
}
let centerLat = (minLat + maxLat) / 2
let centerLong = (minLong + maxLong) / 2
let center = CLLocationCoordinate2D(latitude: centerLat, longitude: centerLong)
let span = MKCoordinateSpan(latitudeDelta: (maxLat - minLat) * 1.5, longitudeDelta: (maxLong - minLong) * 1.5) // with some padding
let region = MKCoordinateRegion(center: center, span: span)
<your MKMapView>.setRegion(region, animated: true)
}
Upvotes: 3
Reputation: 645
Start by removing the group pin
[mapView removeAnnotation:groupAnnotation];
Then add the pins in the cluster
[mapView addAnnotations:clusterAnnotations];
Then determine the region to zoom to
CLLocationDegrees minLat = 90;
CLLocationDegrees maxLat = -90;
CLLocationDegress minLong = 180;
CLLocationDegrees maxLong = -180
[clusterAnnotations enumerateUsingBlock:^(id<MKAnnotation> annotation, NSUInteger idx, BOOL *stop) {
CLLocationCoordinate2D coordinate = annotation.coordinate;
minLat = MIN(minLat, coordinate.latitude);
maxLat = MAX(maxLat, coordinate.latitude);
minLong = MIN(minLong, coordinate.longitude);
maxLong = MAX(maxLong, coordinate.longitude);
}
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((minLat + maxLat)/2.f, (minLong + maxLong)/2.f);
MKCoordinateSpan span = MKCoordinateSpanMake((maxLat - minLat)*1.25, (maxLong - minLong)*1.25); //1.25 is for padding
MKCoordinateRegion region = MKCoordinateRegionMake(center, span);
[mapView setRegion:[mapView regionThatFits:region] animated:YES];
Upvotes: 1