CAAnimation在CALayer上无法正常工作

时间:2015-02-22 10:59:46

标签: ios caanimation cashapelayer

我正试图在UIBezierPath中为CAShapeLayer的外观和消失设置动画。

我希望如何做到这一点,一开始,通过将strokeStartstrokeEnd设置为0,路径将不可见。然后,在我的animate方法中,我会做一个CABasicAnimationstrokeEnd设置为1,然后完成另一个动画,我将strokeStart设置为1,这样路径就会再次消失。这是我尝试过的:

- (void)animate
{
    CAShapeLayer *layer = (CAShapeLayer *)self.layer;

    CABasicAnimation *appearingAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    appearingAnimation.duration = _duration / 2.0;
    appearingAnimation.fromValue = @0;
    appearingAnimation.toValue = @1;

    CABasicAnimation *disappearingAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
    disappearingAnimation.beginTime = _duration / 2.0;
    disappearingAnimation.duration = _duration / 2.0;
    disappearingAnimation.fromValue = @0;
    disappearingAnimation.toValue = @1;

    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    animationGroup.duration = _duration;
    animationGroup.animations = @[appearingAnimation, disappearingAnimation];
    animationGroup.repeatCount = MAXFLOAT;
    [layer addAnimation:animationGroup forKey:@"test"];
}

但我看到的效果是appearingAnimation正常工作,但一旦完成,路径会立即消失而没有任何动画。在此之后(_duration/2.0之后的时间),整个事情重新开始,因此看起来disappearingAnimation没有效果。

我尝试了另一种方法,但只有路径在view.layer上时才有用。一旦我将它添加到子图层并尝试为该图层设置动画,第二个(消失的)动画就会出现故障。这是我的第二种方法:

- (void)animate
{
    CAShapeLayer *layer = (CAShapeLayer *)self.layer;

    layer.strokeStart = 0;
    layer.strokeEnd = 1;

    [CATransaction begin];
    [CATransaction setCompletionBlock:^{
        layer.strokeStart = 1;
        layer.strokeEnd = 1;

        [CATransaction begin];
        [CATransaction setCompletionBlock:^{
             [self animate];
        }];

        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
        animation.duration = _duration / 2.0;
        animation.fromValue = [NSNumber numberWithDouble:0];
        animation.toValue = [NSNumber numberWithDouble:1];
        [layer addAnimation:animation forKey:@"animation1"];
        [CATransaction commit];
    }];
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.duration = _duration / 2.0;
    animation.fromValue = [NSNumber numberWithDouble:0];
    animation.toValue = [NSNumber numberWithDouble:1];
    [layer addAnimation:animation forKey:@"animation"];
    [CATransaction commit];
}

知道为什么第一个解决方案根本不起作用,或者为什么第二个解决方案只能在view.layer而不是sublayer上正常工作?

2 个答案:

答案 0 :(得分:0)

在设置图层属性的动画时,您需要在添加动画之前将图层属性设置为结束值,因为动画更改仅应用于演示文稿,而不是模型图层。动画完成后,它将被移除,使图层处于之前的状态。

创建图层后,您概述的第一种和第二种方法都适用于我(从您的代码段中遗漏):

- (void)animate
{
    CAShapeLayer *layer = [CAShapeLayer layer];
    CGFloat _duration = 2.0;
    CGFloat radius = self.view.frame.size.width/2.0;
    CGFloat startAngle = -(M_PI_2);
    CGFloat endAngle = (3*M_PI_2);
    CGPoint center = CGPointMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0);

    layer.path = [[UIBezierPath bezierPathWithArcCenter:center
                                                 radius:radius
                                            startAngle:startAngle
                                               endAngle:endAngle
                                              clockwise:YES] CGPath];
    layer.fillColor = [[UIColor clearColor] CGColor];
    layer.strokeColor = [[UIColor blackColor] CGColor];
    [self.view.layer addSublayer:layer];

   ... {animation code}
}

答案 1 :(得分:0)

我认为这是_duration / 2.0价值的问题。这可能是浮点数计算的问题。

尽量不要将总持续时间减半,但要将appearingAnimationdisappearingAnimation的持续时间作为基准持续时间:

#define DURATION_BASE 1
// You can choose the DURATION_BASE value whaterver you like

- (void)animate
{
    CAShapeLayer *layer = (CAShapeLayer *)self.layer;

    CABasicAnimation *appearingAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    appearingAnimation.duration = DURATION_BASE;
    appearingAnimation.fromValue = @0;
    appearingAnimation.toValue = @1;

    CABasicAnimation *disappearingAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
    disappearingAnimation.beginTime = appearingAnimation.duration;
    disappearingAnimation.duration = DURATION_BASE;
    disappearingAnimation.fromValue = @0;
    disappearingAnimation.toValue = @1;

    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    animationGroup.duration = appearingAnimation.duration+disappearingAnimation.duration;
    animationGroup.animations = @[appearingAnimation, disappearingAnimation];
    animationGroup.repeatCount = MAXFLOAT;
    [layer addAnimation:animationGroup forKey:@"test"];
}

如果您想更改appearingAnimationdisappearingAnimation的持续时间,只需修改代码

appearingAnimation.duration = DURATION_BASE*1.2;

disappearingAnimation.duration = DURATION_BASE*1.2;