【问题标题】:Why does my rotatable wheel control sometimes spin in the wrong direction?为什么我的可旋转轮控制有时会朝错误的方向旋转?
【发布时间】:2014-08-13 22:02:25
【问题描述】:

我正在制作一个可旋转的轮子控件。您可以拖动它的任何地方以通过它的中心点旋转控件。

它的行为不正确。它通常运行良好,但在旋转的某些部分,它开始向相反方向旋转一小段时间,然后又开始用您的手指旋转。 编辑:经过进一步测试,我意识到您无需将其旋转 360 度即可使其向错误的方向旋转。

一个可能不相关的问题是控件的移动速度似乎比您的手指慢。如果原始问题的解决方案不能解决这个问题,我会提出一个单独的问题。

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

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

#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

编辑:添加日志记录

为什么控件的旋转方向与拖动它的手指不同?

【问题讨论】:

  • 我发现动画是懒惰的。当从角度 A 旋转到角度 B 时,它会想走最短的路线。即,如果旋转超过 180 度,它将想要“向后”。我通过做两次旋转一半来解决这个问题。
  • @HotLicks 好的,我搞定了。你想发布答案,还是我应该?
  • 都是你的——反正我真的不知道我在说什么。

标签: ios rotation transform cgaffinetransform uicontrol


【解决方案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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-25
    相关资源
    最近更新 更多