I've implemented the UIPinchGestureRecognizer on a UIImageView in my app, however no matter where I pinch on the image, it seems to zoom into the same spot. Does anyone know how I can make it zoom in to where a user actually "pinches"? See code below.
ViewController.m
- (IBAction)scaleImage:(UIPinchGestureRecognizer *)recognizer {
recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);
recognizer.scale = 1;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
{
BOOL shouldReceiveTouch = YES;
if (gestureRecognizer == tap) {
shouldReceiveTouch = (touch.view == featureImage);
}
return shouldReceiveTouch;
}
A scale transform leaves the origin (0, 0) untouched. So to scale a view around a particular point, you must first translate that point to the origin, then apply the scale, then translate back.
First, we get the view being pinched.
To compute the center of the pinch, we'll need the midpoint of the view's bounds, so we get the bounds too:
The center is based on the centroid of the pinch's touches, which we get this way:
But we actually need the pinch offset relative to the center of the view, because the view's transform is relative to the center of the view by default. (You can change this by changing the view's
layer.anchorPoint
.)Now we can update the view's transform. First we get its current transform:
Then we update it to translate the pinch center to the origin:
Now we can apply the scale:
Then we translate the view back:
Now we can update the view with the modified transform:
Finally, we reset the gesture recognizer's scale, since we've applied the current scale:
Demo:
Note that in the simulator, you can hold option (alt) for a pinch gesture. Holding shift (while holding option) moves the two touches together.
Here's the code all together for copy/paste:
Rob Mayoff's (@robmayoff) answer is truly inspiring and I wish I had found it earlier. But I actually solved this by changing the anchor point rather than using a transform translation. Effectively it has the same result.
I have not seen this solution on SO (yet...) and figured this was a good place for it.
Transforms work relative to the view layer anchor point. But you can't just set the position point to the pinch center point if the view has been transformed. So here's a method to set the layer anchor point AND correctly convert the position point as well:
And here's the
handlePinch
method that uses thesetAnchorPoint
method to set the layer anchor point to the center point of the pinch touch points:You could simply add a scrollView and in the scrollView add a imageView as below,
Some issue with image upload so check image at this link
Then, you could create a IBOutlet property of scrollView and imageView ,and connect it respectively. Later, add these lines in your viewDidAppear method,
Also add below method,
So now you would get the zoom in/out effects and maximum/minimum zoom limit that u set. Lesser code along with achieving ur goal.
Swift implementation of rob's answer: