I have:
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:
Both pins have to point to the center of their circles:
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
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