如何实现单指旋转手势识别器?

问题描述:

我知道有UIRotateGestureRecognizer已经是iOS的一部分。但是这个手势需要两个手指。如何实现只需要一个手指的类似手势识别器? AppStore中有一个游戏 - Gyrotate,它有很好的实现。任何线索都表示赞赏。谢谢。如何实现单指旋转手势识别器?

+0

只是FWIW - 最好的方法是从根本上理解,如果切线的导数是平滑的,那么它可能是一个很好的用户绘制的圆弧。 切线的导数非常容易计算,概念上并且只需很少的状态 - 您只需要检查最后两帧! 这是识别弧段的“魔术”算法。 – Fattie 2016-04-06 23:41:52

下面是代码 - 它在我的模拟器上工作。马克回答说,如果那是你正在寻找的。

// On new touch, start a new array of points 
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event 
{ 
    self.points = [NSMutableArray array]; 
    CGPoint pt = [[touches anyObject] locationInView:self]; 
    [self.points addObject:[NSValue valueWithCGPoint:pt]]; 
} 

// Add each point to the array 
- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event 
{ 
    CGPoint pt = [[touches anyObject] locationInView:self]; 
    [self.points addObject:[NSValue valueWithCGPoint:pt]]; 
    [self setNeedsDisplay]; 
} 

// At the end of touches, determine whether a circle was drawn 
- (void) touchesEnded:(NSSet *) touches withEvent:(UIEvent *) event 
{ 
    if (!self.points) return; 
    if (self.points.count < 3) return; 

    // Test 1: The start and end points must be between 60 pixels of each other 
    CGRect tcircle; 
    if (distance(POINT(0), POINT(self.points.count - 1)) < 60.0f) 
     tcircle = [self centeredRectangle]; 

    // Test 2: Count the distance traveled in degrees. Must fall within 45 degrees of 2 PI 
    CGPoint center = CGPointMake(CGRectGetMidX(tcircle), CGRectGetMidY(tcircle)); 
    float distance = ABS(acos(dotproduct(centerPoint(POINT(0), center), centerPoint(POINT(1), center)))); 
    for (int i = 1; i < (self.points.count - 1); i++) 
     distance += ABS(acos(dotproduct(centerPoint(POINT(i), center), centerPoint(POINT(i+1), center)))); 
    if ((ABS(distance - 2 * M_PI) < (M_PI/4.0f))) circle = tcircle; 

    [self setNeedsDisplay]; 
} 
+2

不是什么解决了我的问题,而是触发了导致我最终解决方案的时间。 – user292953 2010-11-03 15:51:45

+0

分享,然后 – amok 2010-11-03 22:20:02

+1

啊完美这就是我正在寻找,以及 2011-01-19 16:52:21

尝试探索UIGestureRecognizer Class。你应该可以使用它来定制它UIGestureRecognizerDelegate

柯比特纳有一个完整的单指旋转手势识别器here

+0

我如何执行这个代码的旋转和翻译? – user930195 2011-11-10 14:00:55

+0

你一直在问关于执行“两个”。如果你想检测两个单独的手势,只需使用两个(或更多)UIGestureRecogniser。 – Fattie 2014-06-05 10:18:56

我实现IQStickerViewOneFingerRotation规模调整大小关闭功能。

特点: -

1)单指旋转缩放。

2)一个手指调整大小。

3)启用/取消旋转,缩放,使用属性调整大小。

4)自动管理多个IQStickerView。

5)也可以使用UIScrollView。

6)快速响应。

GitHub的复位器是在这里: - https://github.com/hackiftekhar/IQStickerView

与平移手势识别器来实现,这是使用另一个UIView的手势识别器连接到,但它应该工作与它连接到您要旋转视图。

- (void) gestureRotateButtonPan:(UIPanGestureRecognizer*) gestureRecognizer { 

    switch (gestureRecognizer.state) { 
     case UIGestureRecognizerStatePossible: 
      break; 
     case UIGestureRecognizerStateBegan: 
     { 
      CGPoint location = [gestureRecognizer translationInView:[gestureRecognizer view]]; 
      _touchRotateStartPoint = [self convertPoint:location fromView:[gestureRecognizer view]]; 
     } 
      break; 
     case UIGestureRecognizerStateChanged: 
     { 
      CGPoint imageLocation = CGPointMake(self.mainImageView.transform.tx + self.mainImageView.center.x 
               , self.mainImageView.transform.ty + self.mainImageView.center.y); 
      CGPoint buttonLocation = [gestureRecognizer translationInView:self]; 
      buttonLocation.x += _touchRotateStartPoint.x; 
      buttonLocation.y += _touchRotateStartPoint.y; 

      CGFloat currentRotation = atan2(buttonLocation.y - imageLocation.y, buttonLocation.x - imageLocation.x) 
             - atan2(_touchRotateStartPoint.y - imageLocation.y, _touchRotateStartPoint.x - imageLocation.x); 

      CGFloat rotation = -(_lastRotation - currentRotation); 
      CGAffineTransform currentTransform = self.mainImageView.transform; 
      CGAffineTransform rotatedTransform = CGAffineTransformRotate(currentTransform, rotation); 
      self.mainImageView.transform = rotatedTransform; 

      [self setNeedsDisplay]; 
     } 
      break; 
     case UIGestureRecognizerStateCancelled: 
     case UIGestureRecognizerStateEnded: 
      _lastRotation = 0.0; 
      break; 
     case UIGestureRecognizerStateFailed: 
      break; 
     default: 
      break; 
    } 
}