iOS:完整的360度旋转使用块,而不是CABasicAnimation

这应该是非常简单的事情,但我没有成功地使用块来实现这个function。 这里有一些问题和答案,但是我发现所有这些都是通过使用CABasicAnimation而不是UIView基于块的animation来解决的,而这正是我所追求的。

下面的代码不起作用(基于块),没有animation:

 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; }]; 

根据我的理解,当我们每次使用基于块的时候,都不会发生animation,当UIViewAnimation Block“看到”开始值和最终值相同时。 公平的说,把它设置成360度就意味着对象停留在原来的位置。 但它必须是一种使用基于块的animation来制作这个animation的方法,因为下面的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"]; 

另外,以下基于块的工作,但是在animation之间有一个停止(首先旋转到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度旋转。

提前致谢。

使用UIViewanimation,核心animation计算初始变换和最终变换之间的最短path。 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]; } }]; } 

这是iOS 7的关键帧animation非常适合的东西。 例如,您可以将一个完整的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您可以将所有开始时间和持续时间留空。

这里是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); } }]; } 

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

基于他的代码,我修改了一下来实现一个循环。

 #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]; } }]; 

}