Pinch zoom shifting image to most left corner on iPad in iOS?
Here is a possible solution.
• I've renamed your zoom_image by contentView, because this class can manipulate any view, not only images.
• I've removed the bound tests, and let the scale be in ( 0.01 - 10.0 )
• The pinch handle up to three fingers, and also acts as pan. Number of touches can be changed without interrupting the pinch.
There is still many things to improve, but the main principle is here :)
Interface ( properties like minScale,maxScale, minMargin and so are still to be added - why not a delegate )
@interface PinchViewController : UIViewController@property(nonatomic,strong) IBOutlet UIView* contentView;@end
Implementation
@implementation PinchViewController{ CGPoint translation; CGFloat scale; CGAffineTransform scaleTransform; CGAffineTransform translateTransform; CGPoint previousTranslation; CGFloat previousScale; NSUInteger previousNumTouches;}-(void)viewDidLoad{ scale = 1.0f; scaleTransform = CGAffineTransformIdentity; translateTransform = CGAffineTransformIdentity; previousTranslation = CGPointZero; previousNumTouches = 0; UIPinchGestureRecognizer *pinch=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)]; [self.view addGestureRecognizer:pinch]; UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [panGesture setMinimumNumberOfTouches:1]; [panGesture setMaximumNumberOfTouches:1]; [self.view addGestureRecognizer:panGesture];}-(void)handlePinch:(UIPinchGestureRecognizer*)recognizer{ // 1 - find pinch center CGPoint mid = [self computePinchCenter:recognizer]; mid.x-= recognizer.view.bounds.size.width / 2.0f; mid.y-= recognizer.view.bounds.size.height / 2.0f; // 2 - compute deltas NSUInteger numTouches = recognizer.numberOfTouches; if ( (recognizer.state==UIGestureRecognizerStateBegan) || ( previousNumTouches != numTouches ) ) { previousScale = recognizer.scale; previousTranslation = mid; previousNumTouches = numTouches; } CGFloat deltaScale = ( recognizer.scale - previousScale ) * scale; previousScale = recognizer.scale; CGPoint deltaTranslation = CGPointMake(mid.x-previousTranslation.x, mid.y-previousTranslation.y); previousTranslation = mid; deltaTranslation.x/=scale; deltaTranslation.y/=scale; // 3 - apply scale+=deltaScale; if (scale<0.01) scale = 0.01; else if (scale>10) scale = 10; scaleTransform = CGAffineTransformMakeScale(scale, scale); [self translateBy:deltaTranslation]; NSLog(@"Translation : %.2f,%.2f - Scale Center : %.2f,%.2f - Scale : %.2f",deltaTranslation.x,deltaTranslation.y,mid.x,mid.y,scale);}- (void)handlePan:(UIPanGestureRecognizer *)recognizer{ if (recognizer.state==UIGestureRecognizerStateBegan) previousTranslation = CGPointZero; CGPoint recognizerTranslation = [recognizer translationInView:self.contentView]; CGPoint deltaTranslation = CGPointMake(recognizerTranslation.x - previousTranslation.x,recognizerTranslation.y - previousTranslation.y); previousTranslation = recognizerTranslation; [self translateBy:deltaTranslation]; NSLog(@"Translation : %.2f,%.2f - Scale : %.2f",deltaTranslation.x,deltaTranslation.y,scale);}-(void)translateBy:(CGPoint)delta{ translation.x+=delta.x; translation.y+=delta.y; translateTransform = CGAffineTransformMakeTranslation(translation.x,translation.y); self.contentView.transform = CGAffineTransformConcat(translateTransform,scaleTransform);}-(CGPoint)computePinchCenter:(UIPinchGestureRecognizer*)recognizer{ // 1 - handle up to 3 touches NSUInteger numTouches = recognizer.numberOfTouches; if (numTouches>3) numTouches = 3; // 2 - Find fingers middle point - with (0,0) being the center of the view CGPoint pt1,pt2,pt3,mid; switch (numTouches) { case 3: pt3 = [recognizer locationOfTouch:2 inView:recognizer.view]; case 2: pt2 = [recognizer locationOfTouch:1 inView:recognizer.view]; case 1: pt1 = [recognizer locationOfTouch:0 inView:recognizer.view]; } switch (numTouches) { case 3: mid = CGPointMake( ( ( pt1.x + pt2.x ) / 2.0f + pt3.x ) / 2.0f, ( ( pt1.y + pt2.y ) / 2.0f + pt3.y ) / 2.0f ); break; case 2: mid = CGPointMake( ( pt1.x + pt2.x ) / 2.0f, ( pt1.y + pt2.y ) / 2.0f ); break; case 1: mid = CGPointMake( pt1.x, pt1.y); break; } return mid;}@end
Hope it will help :) Cheers