I want to create an animation with several key frames. I want my Layer (a button in this case) to scale up to 1.5 then down to 0.5 then up to 1.2 then down to 0.8 then 1.0.
I also want to EaseIn and EaseOut of each keyframe.
As you can imagine, this will create a Springy/Bounce effect on the spot.
In other parts of my app I have been using CAKeyframeAnimation like this (see below code). This creates a similar springy animation but for x and y position.
Can I adapt the below code to affect scale instead of position?
Thank you in advance!
- (CAAnimation*)monInAnimation {
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path,NULL,113,320);
CGPathAddLineToPoint(path, NULL, 113.5, 283);
CGPathAddLineToPoint(path, NULL, 113.5, 179);
CGPathAddLineToPoint(path, NULL, 113.5, 207);
CGPathAddLineToPoint(path, NULL, 113.5, 187);
CGPathAddLineToPoint(path, NULL, 113.5, 199);
CGPathAddLineToPoint(path, NULL, 113.5, 193);
CGPathAddLineToPoint(path, NULL, 113.5, 195);
CGPathAddLineToPoint(path, NULL, 113.5, 194);
CAKeyframeAnimation *
animation = [CAKeyframeAnimation
animationWithKeyPath:@"position"];
[animation setPath:path];
[animation setDuration:1.5];
[animation setCalculationMode:kCAAnimationLinear];
NSArray *arr = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],
[NSNumber numberWithFloat:0.12],
[NSNumber numberWithFloat:0.24],
[NSNumber numberWithFloat:0.36],
[NSNumber numberWithFloat:0.48],
[NSNumber numberWithFloat:0.60],
[NSNumber numberWithFloat:0.72],
[NSNumber numberWithFloat:0.84],
[NSNumber numberWithFloat:1.0],nil];
[animation setKeyTimes:arr];
[animation setTimingFunctions:[NSArray arrayWithObjects:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], nil]];
//[animation setAutoreverses:YES];
CFRelease(path);
return animation;
}
- (void)monBtnIn {
[monButton.layer setPosition:CGPointMake(113.5,194)];
[monButton.layer addAnimation:[self monInAnimation]
forKey:@"position"];
}
transform.scale
, anyone?Totally unrelated, if you are gonna use floats in the values array, you must add them as
NSNumbers
, otherwise they'd just end up as 0s!I don't know if you can use a CAKeyframeAnimation for animating the scale of a UIView, but you can do it with a CABasicAnimation and setting the fromValue and toValue properties, and using that to animate the transform property:
Two alternative solutions for you:
First, You can also animate the transform property.
Using Brad's code, but using @"transform" for the keypath. The primary advantage being that you do not have to calculate the actual frame, but instead provide a simple scaling factor:
Objective-C:
Swift 4:
Second, and likely easier, is using FTUtils, an open source wrapper for core animation. It includes a stock "springy" animation.
You can get it at: http://github.com/neror/ftutils
Rather than setting the path of your CAKeyframeAnimation, you'll want to set the keyframes themselves. I've created a "pop-in" effect before by animating the size of the bounds of a layer:
where POPINOVERSHOOTPERCENTAGE is the fraction by which I wanted to overshoot the target size of the layer.