11

它应该是非常简单的,但我还没有成功地使用块来让它工作。对此有问题和答案,但我发现的所有问题都是通过使用CABasicAnimation而不是通过UIView基于块的动画来解决的,这就是我所追求的。

以下代码不起作用(基于块),没有动画:

CGAffineTransform spin = CGAffineTransformRotate(spiningView.transform, DEGREES_RADIANS(360));

CATransform3D identity = CATransform3DIdentity;
CATransform3D spin2 =  CATransform3DRotate(identity, DEGREES_RADIANS(360), 0.0f, 0.0f, 1.0f);


[UIView animateWithDuration:3.0f
                      delay:0.0f
                    options:UIViewAnimationOptionCurveLinear
                 animations:^
                 {
                     spiningView.transform = spin;
                     //spiningView.layer.transform = spin2;
                     //Have also tried the above, doesn't work either.
                 }
                 completion:^(BOOL finished)
                 {
                     spiningView.transform = spin;
                     //spiningView.layer.transform = spin2;
                 }];

据我了解,当我们每次使用 Block-Based 时,当UIViewAnimationBlock“看到”开始值与最终值相同时,不会出现动画。公平地说,将其设置为 360 度将意味着对象保持在原位。但它必须是一种使用基于块的动画来制作动画的方法,因为以下CABasicAnimation将完美地工作:

CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0f];
rotationAnimation.duration = 3.0f;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 1;
[spiningView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];  

此外,以下基于块的作品,但动画之间有一个停止(首先它旋转到 180 度,然后从那里再做 180 度以完成旋转),这不是我所追求的:

[UIView animateWithDuration:3.0f
                      delay:0.0f
                    options:UIViewAnimationOptionCurveLinear
                 animations:^
                 {
                     spiningView.transform = CGAffineTransformRotate(spiningView.transform, DEGREES_RADIANS(180));;
                 }
                 completion:^(BOOL finished)
                 {                         
                     [UIView animateWithDuration:3.0f
                                           delay:0.0f
                                         options:UIViewAnimationOptionCurveLinear
                                      animations:^
                                      {
                                         spiningView.transform = CGAffineTransformRotate(spiningView.transform, DEGREES_RADIANS(360));
                                      }
                                      completion:^(BOOL finished)
                                      {

                                      }];

                 }];

我知道我可以节省很多时间,让自己投入使用CABasicAnimation并完成它,但我想知道为什么在这种情况下一个有效而另一个无效(进行 360 度旋转)。我希望您能给我一个详细的解释,这在本例中的 2 和一些可以进行完整 360 度旋转的代码(基于块)之间。

提前致谢。

4

4 回答 4

27

使用 UIView 动画,Core Animation 计算初始变换和最终变换之间的最短路径。360° 旋转不起作用,因为最终变换与初始变换相同。

对于它的价值,我刚刚尝试了以下代码,它可以平滑地进行四个 90° 旋转,并且旋转之间没有延迟:

- (void)rotateSpinningView
{
    [UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        [spiningView setTransform:CGAffineTransformRotate(spiningView.transform, M_PI_2)];
    } completion:^(BOOL finished) {
        if (finished && !CGAffineTransformEqualToTransform(spiningView.transform, CGAffineTransformIdentity)) {
            [self rotateSpinningView];
        }
    }];
}
于 2013-10-16T15:52:42.820 回答
14

这是 iOS 7 的关键帧动画非常适合的东西。例如,您可以将一个完整的旋转拆分view为三个部分:

CGFloat direction = 1.0f;  // -1.0f to rotate other way
view.transform = CGAffineTransformIdentity;
[UIView animateKeyframesWithDuration:1.0 delay:0.0
                               options:UIViewKeyframeAnimationOptionCalculationModePaced | UIViewAnimationOptionCurveEaseInOut
                            animations:^{
                              [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
                                view.transform = CGAffineTransformMakeRotation(M_PI * 2.0f / 3.0f * direction);
                              }];
                              [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
                                view.transform = CGAffineTransformMakeRotation(M_PI * 4.0f / 3.0f * direction);
                              }];
                              [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.0 animations:^{
                                view.transform = CGAffineTransformIdentity;
                              }];
                            }
                            completion:^(BOOL finished) {}];

请注意,使用时UIViewKeyframeAnimationOptionCalculationModePaced您可以将所有开始时间和持续时间留空。

于 2014-07-16T13:07:57.000 回答
3

这是 neilco 的 rotateSpinningView 的更完整版本。

它顺时针或逆时针旋转。它有一个completion:参数,它很容易启动和停止。

+ (void)rotateSpinningView:(UIView *)view direction:(BOOL)clockwise completion:(void (^)(BOOL finished))completion
{
    int dir = clockwise ? 1 : -1;
    UIViewAnimationOptions opt = UIViewAnimationOptionCurveLinear;
    if (CGAffineTransformEqualToTransform(view.transform, CGAffineTransformIdentity)) {
        opt = UIViewAnimationOptionCurveEaseIn;
    }
    else if (CGAffineTransformEqualToTransform(CGAffineTransformRotate(view.transform, dir * M_PI_2), CGAffineTransformIdentity)) {
        opt = UIViewAnimationOptionCurveEaseOut;
    }
    [UIView animateWithDuration:0.5f delay:0.0f options:opt animations:^{
        [view setTransform:CGAffineTransformRotate(view.transform, dir * M_PI_2)];
    } completion:^(BOOL finished) {
        if (finished && !CGAffineTransformEqualToTransform(view.transform, CGAffineTransformIdentity)) {
            [self rotateSpinningView:view direction:clockwise completion:completion];
        }
        else if (completion && finished && CGAffineTransformEqualToTransform(view.transform, CGAffineTransformIdentity)) {
            completion(finished);
        }
    }];
}
于 2013-11-30T19:13:27.607 回答
1

@neilco 提出了一个非常好的解决方案,但它是无限旋转。

根据他的代码,我进行了一些修改以实现单循环旋转。

#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
- (void)rotateSpinningView:(UIView *)spiningView stop:(BOOL)stop {
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
    double rads = DEGREES_TO_RADIANS(180);
    if (stop) {
        rads = DEGREES_TO_RADIANS(360);
    }
    [spiningView setTransform:CGAffineTransformMakeRotation(rads)];
} completion:^(BOOL finished) {
    if (finished && !stop && !CGAffineTransformEqualToTransform(spiningView.transform, CGAffineTransformIdentity)) {
        [self rotateSpinningView:spiningView stop:YES];
    }
}];

}

于 2015-07-22T21:59:19.540 回答