Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animating a CALayer shadowpath

I'm animating the shadow path for CALayer.

The frame resizes correctly, but the shadow does not scale.

Instead the shadow starts at the final size CGSize(20,20) and holds throughout the animation even though I set the shadowPath to an initial value

[CATransaction begin];
[CATransaction setAnimationDuration: 0];
[CATransaction setDisableActions: TRUE];
    layer.frame = CGRectMake(0,0,10,10);
    layer.shadowPath = [UIBezierPath bezierPathWithRect:layer.bounds].CGPath;
[CATransaction commit];

[CATransaction begin];

    [CATransaction setValue:[NSNumber numberWithFloat:10] forKey:kCATransactionAnimationDuration];
    layer.frame = CGRectMake(0,0,20,20);
    layer.shadowPath = [UIBezierPath bezierPathWithRect:tile.bounds].CGPath;

[CATransaction commit];
like image 901
prostock Avatar asked Aug 12 '12 01:08

prostock


2 Answers

At first, small square with drop shadow.

ss

When button pushed, square and shadow grow bigger together.

ss

The main code is below:

[CATransaction begin];
[CATransaction setAnimationDuration:5.0];
CAMediaTimingFunction *timing = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[CATransaction setAnimationTimingFunction:timing];
layer.frame = CGRectMake(0,0,100,100);
[CATransaction commit];    

CABasicAnimation *shadowAnimation = [CABasicAnimation animationWithKeyPath:@"shadowPath"];
shadowAnimation.duration = 5.0;
shadowAnimation.fromValue = (id)[UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 50, 50)].CGPath;
shadowAnimation.toValue = (id)[UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)].CGPath;
[layer addAnimation:shadowAnimation forKey:@"shadow"];

You can download this project from GitHub and just run it.

https://github.com/weed/p120812_CALayerShadowTest

This question was very hard for me ! :)

like image 68
Feel Physics Avatar answered Oct 20 '22 00:10

Feel Physics


Wanted to add another answer based on Weed's answer. I took weed's answer and tried to put everything in a CATransaction because i wanted to animate multiple layers and be sure animations happened together. Here you guys go if you ever need it. Also, i still don't understand why you have to use the fromValue and toValue in a CATransaction. Why can't you just do the same thing you do with other properties like frame.

[CATransaction begin];

[CATransaction setValue:[CAMediaTimingFunction
    functionWithName:kCAMediaTimingFunctionEaseOut]
    forKey:kCATransactionAnimationTimingFunction];

for (CALayer *layer in self.layers){
    CABasicAnimation *shadowAnimation =
    [CABasicAnimation animationWithKeyPath:@"shadowPath"];

    shadowAnimation.fromValue =
        (id)[UIBezierPath bezierPathWithRect:layer.bounds].CGPath;
    shadowAnimation.timingFunction =
        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    layer.frame = rectFinal;
    shadowAnimation.toValue =
        (id)[UIBezierPath bezierPathWithRect:layer.bounds].CGPath;
    layer.shadowPath =
        [UIBezierPath bezierPathWithRect:layer.bounds].CGPath;
    [layer addAnimation:shadowAnimation forKey:nil];
}         
[CATransaction commit];
like image 34
prostock Avatar answered Oct 20 '22 01:10

prostock