ios - 如何在 Core Animation 中平滑地更新动画的 toValue/end 点?

标签 ios objective-c core-animation cabasicanimation cashapelayer

我正在尝试模拟 Apple 在 iOS 7 中下载应用程序时作为进度指示器的效果,有点像饼图:

enter image description here

我的代码进展顺利。我可以给它一个值,它会更新到那个值。

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];

    CGFloat radius = CGRectGetWidth(self.frame) / 2;
    CGFloat inset  = 1;
    CAShapeLayer *ring = [CAShapeLayer layer];
    ring.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, inset, inset)cornerRadius:radius-inset].CGPath;

    ring.fillColor = [UIColor clearColor].CGColor;
    ring.strokeColor = [UIColor whiteColor].CGColor;
    ring.lineWidth = 2;

    self.innerPie = [CAShapeLayer layer];
    inset = radius/2; 
    self.innerPie.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, inset, inset)
                                               cornerRadius:radius-inset].CGPath;
    self.innerPie.fillColor   = [UIColor clearColor].CGColor;
    self.innerPie.strokeColor = [UIColor whiteColor].CGColor;
    self.innerPie.lineWidth   = (radius-inset)*2;

    [self.layer addSublayer:ring];
    [self.layer addSublayer:self.innerPie];

    self.progress = 0.0;
    self.innerPie.hidden = YES;
}

- (void)setProgress:(CGFloat)progress animated:(BOOL)animated {
    if (animated) {
        self.innerPie.hidden = NO;
        self.innerPie.strokeEnd = progress;

        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        pathAnimation.duration = 0.5;
        pathAnimation.fromValue = [NSNumber numberWithFloat:self.progress];
        pathAnimation.toValue = [NSNumber numberWithFloat:progress];

        [self.innerPie addAnimation:pathAnimation forKey:@"strokeEnd"];
    }
    else {
        [CATransaction setDisableActions:YES];
        [CATransaction begin];
        self.innerPie.hidden = NO;
        self.innerPie.strokeEnd = progress;
        [CATransaction commit];
    }

    self.progress = progress;
}

我的问题在于在动画播放过程中更新进度。例如,如果我正在下载一个文件并且进度从 0.1 跳到 0.2(10% 到 20%),我想为其制作动画。假设我给它一个 0.5 秒的动画。如果在 0.5 秒动画后的 0.2 秒跳到 0.4 (40%) 怎么办?

使用我当前的代码,它会跳到第一个动画 (20%) 中应该结束的位置(当它应该有动画时),然后再次开始向 40% 动画。

我想要的是几乎将 toValue 更新为 0.4。至少那是我认为我想要的。从概念上讲,我希望它在不中断先前值的情况下继续向新值播放动画。平滑度,简单来说。

我将如何完成这个?

我知道有库可以执行此操作。为了学习目的,我想自己做。

最佳答案

你应该替换

pathAnimation.fromValue = [NSNumber numberWithFloat:self.progress];

与:

pathAnimation.fromValue = [NSNumber numberWithFloat:[self.innerPie.presentationLayer strokeEnd]];

最初,[self.innerPie.presentationLayer strokeEnd]] 将为 1,因此您需要将初始值设置为 0。将这两行添加到创建“innerPie”的位置:

self.innerPie.strokeStart = 0;
self.innerPie.strokeEnd = 0;

我已经测试过并且有效。

关于ios - 如何在 Core Animation 中平滑地更新动画的 toValue/end 点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22468782/

相关文章:

ios - 如何快速获取iPhone设备本地存储的文档[pdf,docx,doc,xlsxl]

ios - 带有查询参数的 Post 对象

ios - 如何在 Objective-C 中压缩、解压缩文件(支持 arm64)

css - 如何给一个元素添加两种动画样式

ios - 在 `CAAnimationGroup` 完成后无缝更新图层的视觉属性值?

ios - 为什么在 Xamarin IOS customrenderer 中没有准确检测到长按开始/结束?

ios - 在 Watch InterfaceController.swift 中获取 MMWormhole 的未解析标识符

ios - 使用 Swift 保存和加载高分

objective-c - 错误前预期的说明符限定符列表

ios - 多个 CALayer 动画同时执行