UIImageView 顺时针旋转

10

这应该很简单,但我在旋转一个UIImageView一整圈360度并且永久重复的时候遇到了困难。

[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveLinear | UIViewAnimationOptionBeginFromCurrentState animations:^{
    self.reloadButton.imageView.transform = CGAffineTransformRotate(self.reloadButton.imageView.transform, -M_PI);
} completion:^(BOOL finished) {

}];

根据文档,我传递给 CGAffineTransformRotate 的角度的有无符号决定了旋转的方向,但上述代码是逆时针旋转的。同样适用于M_PI

这个矩阵通过弧度值来旋转坐标系轴。在 iOS 中,正值表示逆时针旋转,负值表示顺时针旋转。在 Mac OS X 中,正值表示顺时针旋转,负值表示逆时针旋转。


如果您使用CATransform3D对imageView的图层进行旋转,会发生什么? - David Rönnqvist
你尝试过旋转其他角度(比如180度)吗? - giorashc
@David 感谢您的建议,但这个操作产生了相同的结果:self.reloadButton.imageView.layer.transform = CATransform3DMakeRotation(-M_PI, 0, 0, 1); - Morrowless
由于M_PI代表180度,因此应该是相同的。如果您旋转我的M_PI/4或-M_PI/4会发生什么?您应该能看到一些差异吗? - Mark
4个回答

14

Christoph已经走了正确的道路,但是有一个更好的方法可以使它保持旋转,而不必每次在动画委托中重新调用它。这样做是错误的。

只需将动画的repeatCount属性设置为HUGE_VALF即可。

CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
animation.fromValue = @0.0f;
animation.toValue = @(2*M_PI);
animation.duration = 0.5f;             // this might be too fast
animation.repeatCount = HUGE_VALF;     // HUGE_VALF is defined in math.h so import it
[self.reloadButton.imageView.layer addAnimation:animation forKey:@"rotation"];

根据文档所述,这将导致动画无限重复。


1
好的,我没有真正考虑过这个问题,因为270度对我来说已经足够了。设置重复次数更好,我会相应地进行更改。 - Christoph
只需使用 CGFLOAT_MAX,而不是导入其他内容。 - Ben Lachman
或者你直接写1e50f,因为它们都是一样的... 或者我们按照文档所述进行操作。 - yinkou
2
@BenLachman 实际上文档明确告诉你要使用 HUGE_VALF。https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CAMediaTiming_protocol/index.html#//apple_ref/occ/intfp/CAMediaTiming/repeatCount - MikeyWard
@MikeyWard 很好的观点,我没有在文档中注意到这一点。你有什么想法为什么他们要指定这个?这是苹果所有文档中唯一一次引用 HUGE_VALF(除了 strto* 手册之外)。看起来有点奇怪。也许是一个遗留的参考? - Ben Lachman
@yinkou 感谢你的讽刺,一直受到赞赏。 :-) HUGE_VALF 似乎是遗留问题。请参阅有关在 Swift 中使用它的此问题:https://dev59.com/OmAf5IYBdhLWcg3wukpk 我想我会就此提出文档错误报告。 - Ben Lachman

1

抱歉,错过了第一部分。使用较小的角度旋转视图完全没有问题:

[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveLinear | UIViewAnimationOptionBeginFromCurrentState animations:^{
        redView.transform = CGAffineTransformRotate(redView.transform, M_PI_2);
    } completion:^(BOOL finished) {

    }];

我找不到任何有意义的解释,为什么它在M_PI上失败了。


重复正是我想要的,问题在于它没有顺时针旋转。 - Morrowless
我认为这是因为旋转的最终状态与原始状态相同。 - giorashc

1

我之前遇到过同样的问题。 我不记得那个问题的原因,但这是我的解决方案:

/**
 * Incrementally rotated the arrow view by a given angle.
 *
 * @param degrees Angle in degrees.
 * @param duration Duration of the rotation animation.
 */
- (void)rotateArrowViewByAngle:(CGFloat)degrees
                  withDuration:(NSTimeInterval)duration {

    CABasicAnimation *spinAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    spinAnimation.fromValue = [NSNumber numberWithFloat:self.currentAngle / 180.0 * M_PI];
    spinAnimation.toValue = [NSNumber numberWithFloat:degrees / 180.0 * M_PI];
    spinAnimation.duration = duration;
    spinAnimation.cumulative = YES;
    spinAnimation.additive = YES;
    spinAnimation.removedOnCompletion = NO;
    spinAnimation.delegate = self;
    spinAnimation.fillMode = kCAFillModeForwards;

    [self.arrowView.layer addAnimation:spinAnimation forKey:@"spinAnimation"];

    self.currentAngle = degrees;
}

接着您可以使用代理方法

- (void)animationDidStart:(CAAnimation *)theAnimation
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag

保持旋转。此外,度数和持续时间参数可以是非常大的数字...如果这足够的话。

更新:
正如yinkou所述,

spinAnimation.repeatCount = HUGE_VALF;     // HUGE_VALF is defined in math.h so import it 

比在委托中重新启动动画要好得多。

请注意:
self.currentAngle是一个属性,用于记住当前的最终旋转角度。
我需要这个来使视图向左和向右旋转。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接