创建动画图层笔划

时间:2016-04-08 11:42:16

标签: objective-c cabasicanimation

我想创建这样的东西,只考虑单循环以及它如何完成一个圆并在完成时反转它:

enter image description here

这段代码完成了我想要的一半:

CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
    drawAnimation.duration            = 1;
    drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
    drawAnimation.toValue   = [NSNumber numberWithFloat:1.0f];

    drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    [circleLayer addAnimation:drawAnimation forKey:@"drawCircleAnimation"];

我尝试将其反转但不起作用:

[CATransaction begin];
    CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
    drawAnimation.duration            = 1;
    drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
    drawAnimation.toValue   = [NSNumber numberWithFloat:1.0f];

    drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    //[circleLayer addAnimation:drawAnimation forKey:@"drawCircleAnimation"];
    [CATransaction setCompletionBlock:^{
        CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        animation2.duration = 1;
        animation2.fromValue = [NSNumber numberWithFloat:0.0f];
        animation2.toValue = [NSNumber numberWithFloat:1.0f];
        animation2.removedOnCompletion = NO;
        animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        [circleLayer addAnimation:animation2 forKey:@"circelBack"];

    }];

    [circleLayer addAnimation:drawAnimation forKey:@"circleFront"];

    [CATransaction commit];

问题是我无法逆转动画。

1 个答案:

答案 0 :(得分:1)

问题

首先,我怀疑你是否以错误的方式获得了动画的关键路径。您应该首先将笔画结束从0设置为1,然后然后笔画从0开始为1。

其次,您永远不会使用新值更新模型图层 - 因此,当动画完成后,图层将会快速恢复'到原来的状态。对你而言,这意味着当第一个动画完成时 - strokeStart将快照回0.0 - 因此反向动画看起来很奇怪。

解决方案

要更新模型图层值,您只需在disableActions块中将YES设置为CATransaction即可防止在图层属性更改时生成隐式动画(赢得'影响显式动画)。然后,您希望在将动画添加到图层后更新模型图层的属性

此外,您可以重复使用CAAnimations - 因为它们在添加到图层时会被复制。因此,您可以为正向和反向动画定义相同的动画,只需更改关键路径。

如果你重复动画,你可能想要将动画定义为ivar - 只需在添加动画之前更新它。

例如,在您的viewDidLoad

@implementation ViewController {
    CABasicAnimation* drawAnimation;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    // define your animation
    drawAnimation = [CABasicAnimation animation];
    drawAnimation.duration = 1;

    // use an NSNumber literal to make your code easier to read
    drawAnimation.fromValue = @(0.0f);
    drawAnimation.toValue   = @(1.0f);

    // your timing function
    drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

    // kick off the animation loop
    [self animate];
}

然后,您想创建一个animate方法,以便执行动画的一次迭代。不幸的是,由于Core Animation不支持在序列中重复多个动画,因此您必须使用递归来实现您的效果。

例如:

-(void) animate {

    if (self.circleLayer.superlayer) { // check circle layer is the layer heirachy before attempting to animate

        // begin your transaction
        [CATransaction begin];

        // prevent implicit animations from being generated
        [CATransaction setDisableActions:YES];

        // reset values
        self.circleLayer.strokeEnd = 0.0;
        self.circleLayer.strokeStart = 0.0;

        // update key path of animation
        drawAnimation.keyPath = @"strokeEnd";

        // set your completion block of forward animation
        [CATransaction setCompletionBlock:^{

            // weak link to self to prevent a retain cycle
            __weak typeof(self) weakSelf = self;

            // begin new transaction
            [CATransaction begin];

            // prevent implicit animations from being generated
            [CATransaction setDisableActions:YES];

            // set completion block of backward animation to call animate (recursive)
            [CATransaction setCompletionBlock:^{
                [weakSelf animate];
            }];

            // re-use your drawAnimation, just changing the key path
            drawAnimation.keyPath = @"strokeStart";

            // add backward animation
            [weakSelf.circleLayer addAnimation:drawAnimation forKey:@"circleBack"];

            // update your layer to new stroke start value
            weakSelf.circleLayer.strokeStart = 1.0;

            // end transaction
            [CATransaction commit];

        }];

        // add forward animation
        [self.circleLayer addAnimation:drawAnimation forKey:@"circleFront"];

        // update layer to new stroke end value
        self.circleLayer.strokeEnd = 1.0;

        [CATransaction commit];
    }
}

要停止动画,您可以从超级图层中删除图层 - 或者实现您自己的布尔检查以确定动画是否应该继续。

enter image description here

完整项目:https://github.com/hamishknight/Circle-Pie-Animation