I want to scale an MKAnnotationView as the map zooms in and out so that if my view takes up 100 meters, it'll continue to visually take up that much.
Here's what I have so far:
- (void)detectPinch:(UIPinchGestureRecognizer*)pinch{
NSArray* annotations = self.mapView.annotations;
for(id<MKAnnotation>annotation in annotations){
if(![annotation isKindOfClass:[MKUserLocation class]] && [annotation isMemberOfClass:[CustomAnnotation class]]){
CustomAnnotationView* annotationView = (CustomAnnotationView*)[self.mapView viewForAnnotation:annotation];
CGAffineTransform transform;
MKZoomScale currentZoomScale = self.mapView.bounds.size.width / self.mapView.visibleMapRect.size.width;
self.previousMapScale = (self.previousMapScale == 0 ? currentZoomScale : self.previousMapScale);
if(self.previousMapScale == currentZoomScale) return;
else transform = CGAffineTransformMakeScale(pinch.scale*((currentZoomScale-self.previousMapScale)+1), pinch.scale*((currentZoomScale-self.previousMapScale)+1));
annotationView.transform = transform;
self.previousMapScale = (pinch.state == UIGestureRecognizerStateEnded ? 0 : currentZoomScale);
}
}
}
This almost works except for every pinch after the first one, the annotation view doesn't keep it's previous state and gets scaled weirdly. After the first call to the pinch gesture recognizer handler, it scales correctly for the rest of the gesture. It's just that initial part of the pinch.
Anybody know where I'm going wrong with my math?
I figured out what I was doing wrong, it wasn't in the math, it was because I was doing transform = CGAffineTransformMakeScale(scale, scale); instead of passing in the existing transform using CGAffineTransformScale. I can't take credit for the math, I found it on an SO post, if I find the post, I'll add the credits at the bottom.
The below code is the complete code for scaling annotations with a map view.
- (void)detectPinch:(UIPinchGestureRecognizer*)pinch{
NSArray* annotations = self.mapView.annotations;
for(id<MKAnnotation>annotation in annotations){
if(![annotation isKindOfClass:[MKUserLocation class]] && [annotation isMemberOfClass:[CustomAnnotation class]]){
CustomAnnotationView* annotationView = (CustomAnnotationView*)[self.mapView viewForAnnotation:annotation];
CGAffineTransform transform;
CGFloat currentScale = self.view.width/self.view.bounds.size.width;
CGFloat newScale = pinch.scale*currentScale;
transform = CGAffineTransformScale(annotationView.transform, newScale, newScale);
annotationView.transform = transform;
pinch.scale = 1;
}
}
}
EDIT:
I figured out a slightly better way to scale the annotation view. Instead of using the scale property on the pinch gesture which sometimes would lead to the view being scaled wrong if the pinch was sharp and quick, simply do this:
CLLocationDistance currentMapWidth = [self.mapView mapWidthInMeters];
CGFloat scale = self.previousMapWidth/currentMapWidth;
//apply the transformation with that scale
self.previousMapWidth = currentMapWidth;
mapWidthInMeters is a category on MKMapView.
- (CLLocationDistance)mapWidthInMeters{
CLLocationDegrees deltaLongitude = self.region.span.longitudeDelta;
CGFloat latitudeCircumference = 40075160 * cos(self.region.center.latitude * M_PI / 180);
return deltaLongitude * latitudeCircumference/360;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With