2

Я пытаюсь повернуть, панорамировать и масштабировать UIView с помощью UIGestureRecognizers. Признаки добавляются в супервизор, в то время как поворот, масштабирование и т. Д. Применяется к subview (_baseImage), это позволяет мне в будущем окутывать другие вещи поверх подсмотра, все еще получая события жестов.Панорамирование, масштабирование, поворот UIView вокруг anchorPoint с использованием UIGestureRecognizer (iOS)

Идея состоит в том, что UIView должен масштабироваться/вращаться вокруг точки «якоря» на подсмотре под двумя точками касания, поскольку это кажется наиболее естественным. У меня возникают проблемы с позицией subview после установки anchorPoint, а также, что масштабирование и вращение не используют набор anchorPoint. Мое понимание понимания перекрывающихся координирующих систем/преобразований CGAffin может вызвать у меня проблемы. Код вытягивается из разных примеров.

Вот мой код, как он стоит на данный момент:

-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view 
{ 
    CGPoint oldOrigin = view.frame.origin; 
    view.layer.anchorPoint = anchorPoint; 
    CGPoint newOrigin = view.frame.origin; 

    CGPoint transition; 
    transition.x = newOrigin.x - oldOrigin.x; 
    transition.y = newOrigin.y - oldOrigin.y; 

    view.center = CGPointMake (view.center.x - transition.x, view.center.y - transition.y); 

} 
- (void) updateTransformWithOffset: (CGPoint) translation 
{ 
    // Create a blended transform representing translation, 
    // rotation, and scaling 
    _baseImage.transform = CGAffineTransformMakeTranslation(translation.x + tx, translation.y + ty); 
    _baseImage.transform = CGAffineTransformRotate(_baseImage.transform, theta); 
    _baseImage.transform = CGAffineTransformScale(_baseImage.transform, scale, scale); 
} 
- (void)adjustAnchorPointForGestureRecognizer:(UIGestureRecognizer *)uigr { 
    if (uigr.state == UIGestureRecognizerStateBegan) { 
     UIView *piece = self.view; 
     CGPoint locationInView = [uigr locationInView:_baseImage]; 
     myFrame = _baseImage.frame; 
     CGPoint newAnchor = CGPointMake((locationInView.x/piece.bounds.size.width), (locationInView.y/piece.bounds.size.height)); 
     [self setAnchorPoint:newAnchor forView:_baseImage]; 
    } 
} 
- (void) handlePinch: (UIPinchGestureRecognizer *) uigr 
{ 
    [self adjustAnchorPointForGestureRecognizer:uigr]; 
    if (uigr.state == UIGestureRecognizerStateBegan) { 
     initScale = scale; 
    } 
    scale = initScale*uigr.scale; 
    [self updateTransformWithOffset:CGPointZero]; 
} 
+0

Да, вы увидите в моем коде, что я использую anchorPoint ... проблема в том, что я не могу заставить его работать должным образом. – user3306929

+0

Я вижу это сейчас. Я просто видел большое количество кода, связанного с преобразованиями. –

+0

Ваши вопросы не очень точные, а ваш код довольно сложный. Я предлагаю вам попробовать и разбить его на куски, которые хорошо работают, и куски, которые имеют проблемы. Затем удалите все остальное, пока не получите минимальный код, который воспроизводит вашу проблему. –

ответ

4

Я нашел решение моей конкретной проблемы с anchorPoint. Я пытался применить преобразования к UIView добавлен в Interface Builder, который вызвал проблемы с точки привязки и установки новой центральной точки, удаляя затем повторно добавив подтаблицы, казалось, чтобы исправить это. Если у кого есть подобные проблемы здесь окончательный код, я использовал на мой взгляд контроллера, это масштаб, поворот и панорамирование на UIView с помощью сенсорной позиции как центра поворота и масштаба:

#import "ViewController.h" 

@interface ViewController(){ 
    CGFloat tx; // x translation 
    CGFloat ty; // y translation 
    CGFloat scale; // zoom scale 
    CGFloat theta; // rotation angle 
    CGFloat initScale ; 
    CGFloat initTheta ; 
} 
@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
    UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotation:)]; 
    [rotationGesture setDelegate:self]; 
    [self.view addGestureRecognizer:rotationGesture]; 
    UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)]; 
    [pinchGesture setDelegate:self]; 
    [self.view addGestureRecognizer:pinchGesture]; 
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; 
    [panGesture setDelegate:self]; 
    [panGesture setMinimumNumberOfTouches:1]; 
    [panGesture setMaximumNumberOfTouches:1]; 
    [self.view addGestureRecognizer:panGesture]; 
    _baseImage.transform = CGAffineTransformIdentity; 
    tx = 0.0f; ty = 0.0f; scale = 1.0f; theta = 0.0f; 
    scale = 1.0; 
    //removing and adding back to the view seems to fix problems with anchor point I was having, I suspect because of IB layout/scaling and constraints etc 
    UIView *mySuperView =_baseImage.superview; 
    [_baseImage removeFromSuperview]; 
    [mySuperView addSubview:_baseImage]; 
} 
-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)myview 
{ 
    CGPoint oldOrigin = myview.frame.origin; 
    myview.layer.anchorPoint = anchorPoint; 
    CGPoint newOrigin = myview.frame.origin; 
    CGPoint transition; 
    transition.x = (newOrigin.x - oldOrigin.x); 
    transition.y = (newOrigin.y - oldOrigin.y); 
    CGPoint myNewCenter = CGPointMake (myview.center.x - transition.x, myview.center.y - transition.y); 
    myview.center = myNewCenter; 
} 
- (void) updateTransformWithOffset: (CGPoint) translation 
{ 
    // Create a blended transform representing translation, 
    // rotation, and scaling 
    _baseImage.transform = CGAffineTransformMakeTranslation(translation.x + tx, translation.y + ty); 
    _baseImage.transform = CGAffineTransformRotate(_baseImage.transform, theta); 
    _baseImage.transform = CGAffineTransformScale(_baseImage.transform, scale, scale); 
} 
- (void)adjustAnchorPointForGestureRecognizer:(UIGestureRecognizer *)uigr { 
    if (uigr.state == UIGestureRecognizerStateBegan) { 
     tx =_baseImage.transform.tx; 
     ty =_baseImage.transform.ty; 
     CGPoint locationInView = [uigr locationInView:_baseImage]; 
     CGPoint newAnchor = CGPointMake((locationInView.x/_baseImage.bounds.size.width), (locationInView.y/_baseImage.bounds.size.height)); 
     [self setAnchorPoint:newAnchor forView:_baseImage]; 
    } 
} 
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 
    // if the gesture recognizers are on different views, don't allow simultaneous recognition 
    if (gestureRecognizer.view != otherGestureRecognizer.view) 
     return NO; 

    if (![gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] && ![otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) { 
     return YES; 
    } 
    return NO; 
} 
- (void) handleRotation: (UIRotationGestureRecognizer *) uigr 
{ 
    if (uigr.state == UIGestureRecognizerStateBegan) { 
     initTheta = theta; 
    } 
    theta = initTheta+uigr.rotation; 
    [self adjustAnchorPointForGestureRecognizer:uigr]; 
    [self updateTransformWithOffset:CGPointZero]; 
} 
- (void) handlePinch: (UIPinchGestureRecognizer *) uigr 
{ 
    if (uigr.state == UIGestureRecognizerStateBegan) { 
     initScale = scale; 
    } 
    scale = initScale*uigr.scale; 
    [self adjustAnchorPointForGestureRecognizer:uigr]; 
    [self updateTransformWithOffset:CGPointZero]; 

} 
- (void) handlePan: (UIPanGestureRecognizer *) uigr 
{ 
    CGPoint translation = [uigr translationInView:_baseImage.superview]; 
    [self adjustAnchorPointForGestureRecognizer:uigr]; 
    [self updateTransformWithOffset:translation]; 
} 
- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

@end 
+0

спасибо, ваш код спас меня – steven274

0

оригинальное решение Ор перевела до Swift 2.0. Я упустил обходное решение, поскольку оно больше не похоже на проблему.

class ViewController: UIViewController { 

    var tx:CGFloat = 0.0 // x translation 
    var ty:CGFloat = 0.0 // y translation 
    var scale:CGFloat = 1.0 // zoom scale 
    var theta:CGFloat = 0.0 // rotation angle 
    var initScale:CGFloat = 1.0 
    var initTheta:CGFloat = 0.0 
    var transformedView: UIView = UIView() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     transformedView.frame = CGRect(x: 0, y: 0, width: 200, height: 200) 
     transformedView.backgroundColor = UIColor.blueColor() 
     view.addSubview(transformedView) 

     let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(OHPlastyViewController.handleRotation(_:))) 
     rotationGesture.delegate = self 
     view.addGestureRecognizer(rotationGesture) 


     let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(OHPlastyViewController.handlePinch(_:))) 
     pinchGesture.delegate = self 
     view.addGestureRecognizer(pinchGesture) 

     let panGesture = UIPanGestureRecognizer(target: self, action: #selector(OHPlastyViewController.handlePan(_:))) 
     panGesture.delegate = self 
     panGesture.minimumNumberOfTouches = 1 
     panGesture.maximumNumberOfTouches = 1 
     view.addGestureRecognizer(panGesture) 

     // The workaround wasn't translated to Swift because it doesn't seem to be needed anymore 
     /* 
     _baseImage.transform = CGAffineTransformIdentity; 
     //removing and adding back to the view seems to fix problems with anchor point I was having, I suspect because of IB layout/scaling and constraints etc 
     UIView *mySuperView =_baseImage.superview; 
     [_baseImage removeFromSuperview]; 
     [mySuperView addSubview:_baseImage];*/ 
    } 

    func setAnchorPoint(anchorPoint: CGPoint, forView myView: UIView) { 
     let oldOrigin: CGPoint = myView.frame.origin 
     myView.layer.anchorPoint = anchorPoint 
     let newOrigin = myView.frame.origin 
     let transition = CGPoint(x: newOrigin.x - oldOrigin.x, y: newOrigin.y - oldOrigin.y) 
     let myNewCenter = CGPoint(x: myView.center.x - transition.x, y: myView.center.y - transition.y) 
     myView.center = myNewCenter 
    } 

    func updateTransformWithOffset(translation: CGPoint) { 
     transformedView.transform = CGAffineTransformMakeTranslation(translation.x + tx, translation.y + ty) 
     transformedView.transform = CGAffineTransformRotate(transformedView.transform, theta) 
     transformedView.transform = CGAffineTransformScale(transformedView.transform, scale, scale) 
    } 

    func adjustAnchorPointForGestureRecognizer(recognizer: UIGestureRecognizer) { 
     if (recognizer.state == .Began) { 
      tx = transformedView.transform.tx 
      ty = transformedView.transform.ty 
      let locationInView = recognizer.locationInView(transformedView) 
      let newAnchor = CGPoint(x: (locationInView.x/transformedView.bounds.size.width), y: (locationInView.y/transformedView.bounds.size.height)) 
      setAnchorPoint(newAnchor, forView: transformedView) 
     } 
    } 

    func handleRotation(recognizer: UIRotationGestureRecognizer) { 
     if recognizer.state == .Began { 
      initTheta = theta 
     } 
     theta = initTheta + recognizer.rotation 
     adjustAnchorPointForGestureRecognizer(recognizer) 
     updateTransformWithOffset(CGPointZero) 
    } 

    func handlePinch(recognizer: UIPinchGestureRecognizer) { 
     if recognizer.state == .Began { 
      initScale = scale 
     } 
     scale = initScale * recognizer.scale 
     adjustAnchorPointForGestureRecognizer(recognizer) 
     updateTransformWithOffset(CGPointZero) 
    } 

    func handlePan(recognizer: UIPanGestureRecognizer) { 
     let translation = recognizer.translationInView(transformedView.superview) 
     adjustAnchorPointForGestureRecognizer(recognizer) 
     updateTransformWithOffset(translation) 
    } 
} 

extension ViewController: UIGestureRecognizerDelegate { 

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { 
     if gestureRecognizer.view != otherGestureRecognizer.view { 
      return false 
     } 

     if !gestureRecognizer.isKindOfClass(UITapGestureRecognizer.self) && !otherGestureRecognizer.isKindOfClass(UITapGestureRecognizer.self) { 
      return true 
     } 
     return false 
    } 
} 
Смежные вопросы