应用完成时,CABasicAnimation会闪烁

时间:2016-06-28 16:07:11

标签: ios objective-c cabasicanimation catransaction

我正在尝试将旋转动画按度数应用于UIImageView,并在完成块中保持旋转变换。

我面临的问题是,当执行完成块时,会有一个可见的闪烁,它是从动画的结束状态传递到完成块。

以下是我目前使用的代码:

if (futureAngle == currentAngle) {
    return;
}

float rotationAngle;
if (futureAngle < currentAngle) {
    rotationAngle = futureAngle - currentAngle;
}else{
    rotationAngle = futureAngle - currentAngle;
}

float animationDuration = fabs(rotationAngle) / 100;
rotationAngle = GLKMathDegreesToRadians(rotationAngle);

[CATransaction begin];
CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.byValue = [NSNumber numberWithFloat:rotationAngle];
rotationAnimation.duration = animationDuration;
rotationAnimation.removedOnCompletion = YES;

[CATransaction setCompletionBlock:^{
    view.transform = CGAffineTransformRotate(view.transform, rotationAngle);
}];

[view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
[CATransaction commit];

2 个答案:

答案 0 :(得分:10)

当你说闪烁时,我认为你的意思是在动画结束时,它会在返回到最终状态之前暂时返回初始状态?这可以通过

解决
  • 在开始动画之前设置最终view.transform(并且您不再需要completionBlock);
  • 将动画的fillMode设置为kCAFillModeForwards并将removedOnCompletion设置为false

就个人而言,我认为在开始动画之前将动画属性设置为其目标值是最简单的方法。

因此:

- (void)rotate:(UIView *)view by:(CGFloat)delta {
    float animationDuration = 2.0;
    CGFloat currentAngle = self.angle;                                                    // retrieve saved angle
    CGFloat nextAngle = self.angle + delta;                                               // increment it
    self.angle = nextAngle;                                                               // save new value

    view.transform = CGAffineTransformMakeRotation(nextAngle);                            // set property to destination rotation

    CABasicAnimation *rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];  // now rotate
    rotationAnimation.fromValue = @(currentAngle);
    rotationAnimation.toValue = @(nextAngle);
    rotationAnimation.duration = animationDuration;
    rotationAnimation.removedOnCompletion = YES;
    [view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

或者,我认为更简单,只需调整transform

即可
- (void)rotate:(UIView *)view by:(CGFloat)delta {
    float animationDuration = 2.0;
    CGAffineTransform transform = view.transform;                                         // retrieve current transform
    CGAffineTransform nextTransform = CGAffineTransformRotate(transform, delta);          // increment it

    view.transform = nextTransform;                                                       // set property to destination rotation

    CABasicAnimation *rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];             // now rotate
    rotationAnimation.fromValue = [NSValue valueWithCGAffineTransform:transform];
    rotationAnimation.toValue = [NSValue valueWithCGAffineTransform:nextTransform];
    rotationAnimation.duration = animationDuration;
    rotationAnimation.removedOnCompletion = YES;
    [view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

答案 1 :(得分:1)

即使使用Rob的建议答案,我也看到闪烁,但事实证明,这似乎只是模拟器错误。在真实设备上,我看不到闪烁,如果您只是在模拟器上进行测试,请在真实设备上尝试,除非您想像自己一样浪费自己的生命。