这应该非常简单,但我还没有成功地使用块来工作。对此有问题和答案,但我发现的所有问题和答案都是通过使用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;
}];
据我了解,每次我们使用基于块时,都不会发生动画,当UIViewAnimation
块"看到"开始值与最终值相同时。公平地说,将其设置为移动到 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 度旋转的代码(基于块)之间给我一个详细的解释。
提前谢谢。
对于 UIView 动画,核心动画计算初始转换和最终转换之间的最短路径。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的关键帧动画非常适合的。例如,您可以将一个完整的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提出了一个非常好的解决方案,但它是一个无限旋转。
根据他的代码,我修改了一点以实现单循环旋转。
#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];
}
}];
}