创建动画图层笔划

问题描述 投票:1回答:1

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

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];

问题是我无法扭转动画。

objective-c cabasicanimation
1个回答
1
投票

The Problem

首先,我怀疑你的动画关键路径是错误的。首先应该将笔划结束的动画从0设置为1,然后笔划从0开始为1。

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


The Solution

要更新模型图层值,您只需在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

© www.soinside.com 2019 - 2024. All rights reserved.