Using PinchGesture; How can I zoom in to where the user fingers actually “pinch”?

I implemented the UIPinchGestureRecognizer in a UIImageView in my application, however no matter where I capture the image, it seems to be approaching the same place. Does anyone know how I can get it to zoom in to where the 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; } 
+5
source share
4 answers

A large-scale conversion leaves the start (0, 0) untouched. To scale a view around a specific point, you must first translate that point to the origin, then apply the scale, and then translate back.

 - (IBAction)pinchGestureDidFire:(UIPinchGestureRecognizer *)pinch { 

First, we get a view that is pinched.

  UIView *pinchView = pinch.view; 

To calculate the center of the pinch, we need the midpoint of the view boundaries, so we also get the borders:

  CGRect bounds = pinchView.bounds; 

The center is based on the center of gravity of the touch, which we get as follows:

  CGPoint pinchCenter = [pinch locationInView:pinchView]; 

But we really need a pinch offset relative to the center of the view, because the default view transformation is relative to the center of the view. (You can change this by changing the presentation of layer.anchorPoint .)

  pinchCenter.x -= CGRectGetMidX(bounds); pinchCenter.y -= CGRectGetMidY(bounds); 

Now we can update the view transformation. First we get its current conversion:

  CGAffineTransform transform = pinchView.transform; 

Then we update it to translate the pinch center to the beginning:

  transform = CGAffineTransformTranslate(transform, pinchCenter.x, pinchCenter.y); 

Now we can apply the scale:

  CGFloat scale = pinch.scale; transform = CGAffineTransformScale(transform, scale, scale); 

Then translate the view back:

  transform = CGAffineTransformTranslate(transform, -pinchCenter.x, -pinchCenter.y); 

Now we can update the view using a modified transformation:

  pinchView.transform = transform; 

Finally, we reset the gesture recognition scale since we applied the current scale:

  pinch.scale = 1.0; } 

Demo:

pinch scale

Please note that in the simulator you can hold the (alt) option for hard pressing. Holding shift (while holding) moves two touches together.

Here is all the code to copy / paste:

 - (IBAction)pinchGestureDidFire:(UIPinchGestureRecognizer *)pinch { UIView *pinchView = pinch.view; CGRect bounds = pinchView.bounds; CGPoint pinchCenter = [pinch locationInView:pinchView]; pinchCenter.x -= CGRectGetMidX(bounds); pinchCenter.y -= CGRectGetMidY(bounds); CGAffineTransform transform = pinchView.transform; transform = CGAffineTransformTranslate(transform, pinchCenter.x, pinchCenter.y); CGFloat scale = pinch.scale; transform = CGAffineTransformScale(transform, scale, scale); transform = CGAffineTransformTranslate(transform, -pinchCenter.x, -pinchCenter.y); pinchView.transform = transform; pinch.scale = 1.0; } 
+20
source

Fast implementation of a rob response:

 @objc private func pinchHandler(gesture: UIPinchGestureRecognizer) { if let view = gesture.view { switch gesture.state { case .changed: let pinchCenter = CGPoint(x: gesture.location(in: view).x - view.bounds.midX, y: gesture.location(in: view).y - view.bounds.midY) let transform = view.transform.translatedBy(x: pinchCenter.x, y: pinchCenter.y) .scaledBy(x: gesture.scale, y: gesture.scale) .translatedBy(x: -pinchCenter.x, y: -pinchCenter.y) view.transform = transform gesture.scale = 1 case .ended: // Nice animation to scale down when releasing the pinch. // OPTIONAL UIView.animate(withDuration: 0.2, animations: { view.transform = CGAffineTransform.identity }) default: return } } } 
+4
source

You can simply add scrollView and add image to scrollView as shown below,

 ![ImageView on top of scrollView][1] 

There is some problem loading the image, so check the image on this

Then you can create an IBOutlet property for scrollView and imageView and connect it accordingly. Later add these lines to your viewDidAppear method,

 _scrollView.maximumZoomScale = 10.0; //Maximum Zoom _scrollView.minimumZoomScale = minimumScale; //Minimum Zoom 

Also add below method

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

So now you get the zoom in / out effects and the maximum / minimum zoom limit that you set. Small code along with achievement of ur goal

0
source
 ViewController.h @property (strong, nonatomic) IBOutlet UIImageView *img; ViewController.m - (void)viewDidLoad { [super viewDidLoad]; UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchDetected:)]; [_img addGestureRecognizer:pinchRecognizer]; // Do any additional setup after loading the view, typically from a nib. } - (void)pinchDetected:(UIPinchGestureRecognizer *)pinchRecognizer { CGFloat scale = pinchRecognizer.scale; _img.transform = CGAffineTransformScale(self.img.transform, scale, scale); pinchRecognizer.scale = 1.0; } 
-1
source

Source: https://habr.com/ru/post/1202635/


All Articles