Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scale MKAnnotationView with Map Zoom

Tags:

ios

mkmapview

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?

like image 971
barndog Avatar asked Mar 23 '26 15:03

barndog


1 Answers

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;
}
like image 195
barndog Avatar answered Mar 25 '26 05:03

barndog



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!