2

我想使用UIGestureRecognizers旋轉,平移和縮放UIView。將識別器添加到超級視圖中,而旋轉,縮放等應用於子視圖(_baseImage),這是爲了使我能夠在未來接收手勢事件的同時在子視圖頂部覆蓋其他內容。使用UIGestureRecognizer(iOS)平移,縮放和旋轉UIView圍繞anchorPoint使用UIGestureRecognizer(iOS)

這個想法是,UIView應該縮放/旋轉兩個觸摸點下面的子視圖上的「錨點」,因爲這看起來是最自然的。我遇到的問題是在設置anchorPoint之後子視圖的位置,以及縮放和旋轉似乎沒有使用set anchorPoint。我對重疊座標系統/ CGAffine變換缺乏瞭解可能會讓我陷入困境。代碼來自各種示例。

這裏是我的代碼,因爲它代表的時刻:

-(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中,導致錨點出現問題,並設置新的中心點,刪除然後重新添加子視圖似乎修復它。

#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

的OP的原液譯:如果任何人有類似的問題在這裏是我在我的視圖控制器上使用的最終代碼,但它的規模,使用爲中心的旋轉和縮放的觸摸位置旋轉,平移一個UIView 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 
    } 
}