平滑地旋转刷新按钮图像,使其完成到最近的旋转iOS



我正在尝试动画刷新按钮,使其旋转,表明刷新正在进行中。它需要平滑,这样如果刷新只需要0.1秒,我们仍然会做一个完整的旋转,这样用户就可以知道发生了什么,这是一个平滑的过渡。它也应该继续旋转,直到我停止它,但是停止不应该突然停止,它只告诉它完成当前的转弯。

最初我是这样做的

CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat:M_PI * 2.0 * 10];
rotationAnimation.cumulative = YES;
rotationAnimation.duration = 10;
[self.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];

像这样停下来

[self.layer removeAllAnimations];

这在动画平滑地持续超过2圆周率的意义上工作得很好,但是当刷新时间少于1/10秒时,它看起来就不那么平滑了,因为动画会在旋转10%的时候突然停止,removeAllAnimations方法会将图像重置为默认值。

我设法绕过这个替代停止方法

    CALayer *presentLayer = self.layer.presentationLayer;
    float currentAngle = [(NSNumber *) [presentLayer valueForKeyPath:@"transform.rotation.z"] floatValue];
    [self.layer removeAllAnimations];   
    if (currentAngle < 0) {
        currentAngle = 2 * ABS(currentAngle);
    }
    float rotationProgressPercent = currentAngle / (2 * M_PI);    
    CABasicAnimation *rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.fromValue = [NSNumber numberWithFloat:currentAngle];
    rotationAnimation.toValue = [NSNumber numberWithFloat:M_PI * 2];
    rotationAnimation.cumulative = YES;
    rotationAnimation.duration = 1 - rotationProgressPercent;

基本上,我以弧度为单位获得当前旋转角度,停止动画并从该位置开始一个新的动画。我必须对持续时间做一些工作,以保持速度恒定,速度方面工作得很好,但问题是动画有一个非常轻微的延迟/抽搐。我相信这是因为停止动画是异步发布这个请求到系统(这只是猜测),我当前的角度是陈旧的时候,我去做我的第二个动画。

所以我最终找到了一个解决方案,这是如何有用的

-(void)startSpinning {
    if (animating) {
        return;
    }
    animating = YES;
    [self rotateViewWithDuration:1 byAngle:M_PI * 2];
}
- (void)stopSpinning {
    animating = NO;
}

- (void)rotateViewWithDuration:(CFTimeInterval)duration byAngle:(CGFloat)angle {

    [CATransaction begin];
    CABasicAnimation *rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.byValue = [NSNumber numberWithFloat:angle];
    rotationAnimation.duration = duration;
    rotationAnimation.removedOnCompletion = YES;
    [CATransaction setCompletionBlock:^{
        if (animating) {
            [self rotateViewWithDuration:duration byAngle:angle];
        }
    }];
    [self.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
    [CATransaction commit];
}

最新更新