Animate previously added CALayer animations

194 views Asked by At

I'm working on a component that is supposed to render several images and animate their position while changing also the contents. I've been inspired by this post: http://ronnqvi.st/controlling-animation-timing/ and thought of using speed to control the animations.

My ideia is to add the CALayers with the animations to a top-level layer whose speed is 0 and then set this layer's speed to 1.0 when it's time to animate.

Here's the code for it:

...

@property (nonatomic,strong) CALayer *animationLayer;

...

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) 
    {
         self.animationLayer = [CALayer layer];
         self.animationLayer.frame = frame;
         self.animationLayer.speed = 0.0;
         [self.layer addSublayer:self.animationLayer];
    }
    return self;
}

- (void)addLayerData:(LayerData*)layerData
{
    CALayer *aLayer = [CALayer layer];
    aLayer.contents = (id) layerData.image.CGImage;
    aLayer.frame = CGRectMake(0,0,96,96);
    aLayer.position = layerData.position;
    aLayer.name = layerData.name;

    CGRect pathLayerFrame = layerData.path.bounds;
    pathLayerFrame.origin.x = 0.0;
    pathLayerFrame.origin.y = 0.0;

    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.frame = pathLayerFrame;
    pathLayer.path = layerData.path.CGPath;
    pathLayer.strokeColor = layerData.strokeColor.CGColor;
    pathLayer.fillColor = [UIColor clearColor].CGColor;
    pathLayer.lineWidth = 10;
    pathLayer.lineCap = kCALineCapRound;

    [self.animationLayer addSublayer:pathLayer];

    CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    [positionAnimation setPath: layerData.path.CGPath];
    [positionAnimation setDuration: 10.0];
    [positionAnimation setRemovedOnCompletion: NO];
    [positionAnimation setFillMode: kCAFillModeBoth];
    [positionAnimation setKeyTimes:layerData.keyTimes];

    CAKeyframeAnimation *contentsAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
    [contentsAnimation setValues:[self buildContentImagesFromLayerData:layerData];
    [contentsAnimation setCalculationMode:kCAAnimationDiscrete];
    contentsAnimation.calculationMode = kCAAnimationLinear;
    [contentsAnimation setDuration:0.1];
    [contentsAnimation setDelegate:self];
    [contentsAnimation setAutoreverses:YES];
    [contentsAnimation setRepeatCount:HUGE_VALF];
    [contentsAnimation setRemovedOnCompletion:NO];
    [contentsAnimation setFillMode:kCAFillModeBoth];

    [aLayer addAnimation:positionAnimation forKey:kPostionAnimationKey];
    [aLayer addAnimation:contentsAnimation forKey:kContentsAnimationKey];

    [self.animationLayer addSublayer:aLayer];
}

- (void)animate
{
     self.animationLayer.speed = 1.0;
}

My issue is that although the animationLayer contains all the layers to animate and these have all the animations correctly defined I can't seem to get the layers moving around the screen.

The addLayerData is called several times by external client code, at different times (that is when user taps a button to add an image). The animate is called after that when the user taps a button.

Maybe I've missed something in the article.

Can anyone help me out on this one?

Thanks in advance.

UPDATE

If I drop the animationLayer and add the layers to be animated directly on the view's layer (self.layer) it works correctly.

0

There are 0 answers