2014-09-16 10 views
5

Ich habe den UIPinchGestureRecognizer auf einem UIImageView in meiner App implementiert, aber egal, wo ich auf das Bild klicke, scheint es in die gleiche Stelle zu zoomen. Weiß jemand, wie ich es zoomen kann, wo ein Benutzer tatsächlich "klemmt"? Siehe Code unten.Verwenden von PinchGesture; Wie kann ich hineinzoomen, wo die Finger eines Benutzers tatsächlich "einklemmen"?

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; 
} 

Antwort

19

Eine Skala-Transformations verlässt den Ursprung (0, 0) unberührt. Um eine Ansicht um einen bestimmten Punkt herum zu skalieren, müssen Sie diesen Punkt zuerst in den Ursprung übersetzen, dann die Skala anwenden und dann zurück übersetzen.

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

Zuerst bekommen wir die Ansicht eingeklemmt.

UIView *pinchView = pinch.view; 

das Zentrum der Quetschung zu berechnen, werden wir den Mittelpunkt der Grenzen des Ansicht benötigen, so erhalten wir die auch Grenzen gesetzt:

CGRect bounds = pinchView.bounds; 

Das Zentrum auf den Schwerpunkt der Quetschung des basiert berührt, die wir auf diese Weise erhalten:

CGPoint pinchCenter = [pinch locationInView:pinchView]; 

Aber wir brauchen eigentlich die Prise in die Mitte der Ansicht versetzt, weil der Blick auf die Mitte der Ansicht standardmäßig relativ Transformation des ist. (Sie können dies durch die layer.anchorPoint Ansicht zu ändern ändern.)

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

Jetzt können wir die Ansicht der Transformation aktualisieren. Zuerst bekommen wir seine aktuelle Transformation:

CGAffineTransform transform = pinchView.transform; 

Dann aktualisieren wir die Prise Zentrum auf den Ursprung zu übersetzen:

Jetzt können wir den Maßstab anwenden:

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

Dann wir übersetzen Sie die Ansicht zurück:

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

Jetzt können wir die Ansicht mit der Transformation modifiziert aktualisieren:

pinchView.transform = transform; 

Schließlich haben wir die Gestenerkenner-Skala zurückgesetzt, da wir den aktuellen Maßstab angewendet haben:

pinch.scale = 1.0; 
} 

Demo:

pinch scale

Beachten Sie, dass Sie im Simulator die Option (Alt) für eine Pinch-Geste halten können. Wenn Sie die Umschalttaste gedrückt halten (während Sie die Option gedrückt halten), werden die beiden Berührungen zusammengeführt.

Hier ist der Code alle zusammen für Kopieren/Einfügen:

- (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; 
} 
+0

Dies scheint nicht für mich zu arbeiten (obwohl es scheint, wie es sollte)? Ich habe das oben beschriebene implementiert und kann immer noch nur auf eine Stelle des Bildes zoomen. – Brittany

+1

Sind Sie sicher, dass Sie den Gestenerkenner mit der neuen Methode verbunden haben und ihn nicht mit der alten Methode verbunden haben? Haben Sie einen 'NSLog' oder einen Haltepunkt in die neue Methode eingefügt, um sicherzustellen, dass er aufgerufen wird? –

+0

ist es möglich, nicht proportional Zoom anzuwenden? Ich meine, dass x und y sich einzeln ändern? – user5599807

0

Sie einfach als unten, eine Scrollview und in der Scrollview fügen Sie ein Imageview hinzufügen könnte

![ImageView on top of scrollView][1] 

Einige Ausgabe mit Bild-Upload so Überprüfen Sie das Bild an dieser Stelle link

Dann können Sie eine IBOutlet-Eigenschaft von scrollView und imageView erstellen und verbinden Sie jeweils. Später fügen Sie diese Zeilen in Ihrer viewDidAppear Methode,

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

Auch unter Methode hinzufügen,

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

So, jetzt würden Sie den Zoom in/out-Effekte und maximale/minimale Zoomgrenze erhalten, die u gesetzt. Lesser Code zusammen mit dem Erreichen Ihres Ziels.

+0

Ich würde dies tun, aber ich mag nicht die Idee, die Bildlaufleiste auf dem gezoomten Bild zu sehen:/ – Brittany

+0

Idee in der Lage zu sehen, Bildlaufleiste ist es, den Benutzer wissen, dass er sich bewegen konnte, um zu sehen das Bild (wie im gezoomten Fall würde er die Kunst des vollständigen Bildes sehen) – nikhil84

+0

Sie können die Bildlaufleisten vom Interface Build deaktivieren, indem Sie die Optionen "Show Horizontal/Vertical Indicator" deaktivieren. Es kann sogar programmgesteuert erfolgen. –

-1
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; 
} 
2

Swift Umsetzung von rob Antwort:

@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 
     } 


    } 
}