Question

I have:

  • an UIScrollView
  • UIImageView as subview of the previous scrollview (it's a very big background image with 1 green circle and 1 red circle). It has 2 two subviews:

    1. first pin image (a white cross)
    2. second pin image (an orange custom map pin)

Both pins have to point to the center of their circles:

  • the center of the white cross must be on the center of the green circle
  • the bottom peak of the orange map-pin must be on the center of the red circle.

This is the desired behavior and, when the App start, I got it.
(I have also successfully apply inverted transform to prevent both pins from scaling with the big background image while zooming (as explained by Andrew Madsen in another post).

The problem
When I zoom in/out, orange pin (which have a kind of "centerOffset") seems move up/down because its bottom peak lost the center of red circle.
(while white cross is ok because it is always centered with the circle)

See 1 example of correct behavior (at launch) and 2 examples of wrong behavior here: https://www.dropbox.com/s/8stjh892wm8yfdb/123.png

I've also try to subclass a MKAnnotationView for the orange pin, and set centerOffset:

self.centerOffset = CGPointMake(0,-self.image.size.width/2); 

in
- (void)setAnnotation:(id <MKAnnotation>)annotation,
but it is ignored (maybe because it's not on a mkmapview).


How can I set the bottom peak of orange pin to follow the center of red circle while zooming in/out?

I repeat it for clarify: I don't want that the center of orange pin be always on the center of red circle, I want that the bottom peak of the orange pin be always on the center of red circle.

Here is sample code of the ViewController

#import <QuartzCore/QuartzCore.h>
#import "TestViewController.h"


@implementation TestViewController

@synthesize scrollView;

//SLImageView is my extension of UIImageView with the invertedTransform (see: http://stackoverflow.com/questions/12981201/keep-subviews-of-uiscrollview-from-resizing)
@synthesize backgroundImageView;

- (void)viewDidLoad
{
    [super viewDidLoad];
    UIImage *image = [UIImage imageNamed:@"circles.png"];


    self.backgroundImageView = [[SLImageView alloc] initWithImage:image];
    self.backgroundImageView.frame = (CGRect){.origin=CGPointMake(0.0f, 0.0f), .size=image.size};
    [self.scrollView addSubview:self.backgroundImageView];

    // Tell the scroll view the size of the contents
    self.scrollView.contentSize = image.size;


}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // Set up the minimum & maximum zoom scales
    CGRect scrollViewFrame = self.scrollView.frame;
    CGFloat scaleWidth = scrollViewFrame.size.width / self.scrollView.contentSize.width;
    CGFloat scaleHeight = scrollViewFrame.size.height / self.scrollView.contentSize.height;
    CGFloat minScale = MIN(scaleWidth, scaleHeight);
    self.scrollView.minimumZoomScale = minScale;
    self.scrollView.maximumZoomScale = 4.0f;
    self.scrollView.delegate = self;

    UIImageView *topWhiteCrossPin = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cross.png"]];
    topWhiteCrossPin.center = CGPointMake(110, 304);

    UIImageView *topOrangeMapPin = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"centerOffsetPin.png"]];
    topOrangeMapPin.center = CGPointMake(284, 288);

    [backgroundImageView addSubview:topWhiteCrossPin];
    [backgroundImageView addSubview:topOrangeMapPin];

    self.scrollView.zoomScale = minScale * 3.5;
}


- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return backgroundImageView;
}


@end

Complete example xcode project here: https://www.dropbox.com/s/rvohsn1wemd4lyj/AffineTransformExample.zip

Thanks in advance.
Mick

Was it helpful?

Solution

After another night of test I've finally found the trick and it's very simple. Add [topOrangeMapPin.layer setAnchorPoint:CGPointMake(0.5, 1)]; just after topOrangeMapPin.center = CGPointMake(284, 308);. This will set the anchor point at the middle of bottom of orange pin, just where ther is its peak. Any consequent affine transform will use this new anchor point. This trick was not so obvious for a beginner like me

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top