为什么我的可旋转轮控制有时会向错误的方向旋转?

时间:2014-08-13 22:02:26

标签: ios rotation transform cgaffinetransform uicontrol

我正在进行可旋转的车轮控制。您可以拖动它的任何位置来旋转控件的中心点。

行为不正确。它通常效果很好,但是对于旋转的某些部分,它会在相反方向开始短时间,然后再次用手指开始旋转。 编辑:经过进一步测试,我意识到你不需要将它旋转360度,以便它以错误的方向旋转。

一个可能不相关的问题是控件似乎比你的手指移动得慢。如果原问题的解决方案无法解决这个问题,我会问一个单独的问题。

我发布了example project。如果您希望自己重现项目,请执行以下步骤:

  1. 创建新的单一视图应用程序。
  2. 创建一个名为UIView
  3. 的新NNReadyIndicator子类(在Objective-C中)
  4. 将此代码复制并粘贴到`NNReadyIndi​​cator.m
  5. #import "NNReadyIndicator.h"

    @interface NNReadyIndicator ()
    
    @property CGAffineTransform startTransform;
    
    @property double originalAngle;
    
    @end
    
    @implementation NNReadyIndicator
    
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect {
        // Drawing code
     }
     */
    
    #pragma mark tracking
    
    - (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
        CGPoint touchPoint = [touch locationInView:self];
    
        [self setOriginalAngle:[NNReadyIndicator calculateAngleWithX1:touchPoint.x x2:self.center.x y1:touchPoint.y y2:self.center.y]];
        [self setStartTransform:self.transform];
    
        NSLog(@"BEGIN TRACKING  | originalAngle: %f", self.originalAngle);
    
        return YES;
    }
    
    - (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
        CGPoint touchPoint = [touch locationInView:self];
        double angle = [NNReadyIndicator calculateAngleWithX1:touchPoint.x x2:self.center.x y1:touchPoint.y y2:self.center.y];
        CGFloat angleDifference = (CGFloat)(self.originalAngle - angle);
    
        [self setTransform: CGAffineTransformRotate(self.startTransform, -angleDifference)];
    
        NSLog(@"CONTINUE TRACKING |       angle: %f angleDifference: %f", angle, angleDifference);
    
        return YES;
    }
    
    #pragma mark -- Calculate Angle
    
    + (double)calculateAngleWithX1:(double)x1 x2:(double)x2 y1:(double)y1 y2:(double)y2 {
        double distanceX = [NNReadyIndicator calculateDistanceWithPoint:x1 point:x2];
        double distanceY = [NNReadyIndicator calculateDistanceWithPoint:y1 point:y2];
    
        return [self calculateAngleWithDistanceX:distanceX distanceY:distanceY];
    }
    
    + (double)calculateDistanceWithPoint:(double)pointA point:(double)pointB {
        double distance = pointA - pointB;
    
        if (distance < 0) {
            distance = -distance;
        }
    
        return distance;
    }
    
    + (double)calculateAngleWithDistanceX:(double)distanceX distanceY:(double)distanceY {
        return atan2(distanceY, distanceX);
    }
    
    @end
    

    编辑:添加了记录

    为什么控件不能像拖动它的手指一样在同一方向(并以相同的速度?)旋转?

1 个答案:

答案 0 :(得分:1)

如果角度高于或低于360度,则需要翻转角度。此外,为了使其更容易理解,您必须将其转换为度数然后返回。基于这个答案:https://stackoverflow.com/a/19617316/2564682

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)

- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
    CGPoint touchPoint = [touch locationInView:self];
    double angle = [NNReadyIndicator calculateAngleWithX1:touchPoint.x x2:self.center.x y1:touchPoint.y y2:self.center.y];

    double angleInDegrees = angle * 180 / M_PI;

    // Flip angle if above or below 360 degrees
    if (angleInDegrees > 180) {
        angleInDegrees -= 360;
    } else if (angleInDegrees < -180) {
        angleInDegrees += 360;
    }

    CGFloat angleDifference = (CGFloat)(self.originalAngle - angleInDegrees);

    [self.layer setTransform: CATransform3DRotate(self.layer.transform, (float)DEGREES_TO_RADIANS(-angleDifference), .0, .0, 1.0)];

    NSLog(@"CONTINUE TRACKING |       angle: %f angleDifference: %f", angleInRadians, angleDifference);

    return YES;
}