我想创建一个包含几个关键帧的动画。我想要我的图层(在这种情况下是一个按钮) 扩大到1.5然后下降到0.5然后上升到1.2然后下降到0.8然后是1.0。
我也想要每个关键帧的EaseIn和EaseOut。
你可以想象,这会在现场产生一个弹跳/弹跳效果。
在我的应用程序的其他部分,我一直在使用CAKeyframeAnimation(见下面的代码)。 这会产生类似的弹性动画,但是对于x和y位置。
我可以调整以下代码来影响比例而不是位置吗?
提前谢谢!
- (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"];
}
答案 0 :(得分:28)
为您提供两种替代解决方案:
首先,您还可以为转换属性设置动画。
使用Brad的代码,但使用@“transform”作为密钥路径。主要优点是您不必计算实际帧,而是提供简单的缩放因子:
<强>目标C 强>:
CAKeyframeAnimation *boundsOvershootAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
CATransform3D startingScale = CATransform3DScale (layer.transform, 0, 0, 0);
CATransform3D overshootScale = CATransform3DScale (layer.transform, 1.2, 1.2, 1.0);
CATransform3D undershootScale = CATransform3DScale (layer.transform, 0.9, 0.9, 1.0);
CATransform3D endingScale = layer.transform;
NSArray *boundsValues = [NSArray arrayWithObjects:[NSValue valueWithCATransform3D:startingScale],
[NSValue valueWithCATransform3D:overshootScale],
[NSValue valueWithCATransform3D:undershootScale],
[NSValue valueWithCATransform3D:endingScale], nil];
[boundsOvershootAnimation setValues:boundsValues];
NSArray *times = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:0.5f],
[NSNumber numberWithFloat:0.9f],
[NSNumber numberWithFloat:1.0f], nil];
[boundsOvershootAnimation setKeyTimes:times];
NSArray *timingFunctions = [NSArray arrayWithObjects:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
nil];
[boundsOvershootAnimation setTimingFunctions:timingFunctions];
boundsOvershootAnimation.fillMode = kCAFillModeForwards;
boundsOvershootAnimation.removedOnCompletion = NO;
Swift 4 :
let boundsOvershootAnimation = CAKeyframeAnimation(keyPath: "transform")
let startingScale = CATransform3DScale(layer.transform, 0, 0, 0)
let overshootScale = CATransform3DScale(layer.transform, 1.2, 1.2, 1.0)
let undershootScale = CATransform3DScale(layer.transform, 0.9, 0.9, 1.0)
let endingScale = layer.transform
boundsOvershootAnimation.values = [startingScale, overshootScale, undershootScale, endingScale]
boundsOvershootAnimation.keyTimes = [0.0, 0.5, 0.9, 1.0].map { NSNumber(value: $0) }
boundsOvershootAnimation.timingFunctions = [
CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseOut),
CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut),
CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)
]
boundsOvershootAnimation.fillMode = kCAFillModeForwards
boundsOvershootAnimation.isRemovedOnCompletion = false
其次,可能更容易,使用FTUtils,一个用于核心动画的开源包装器。它包括一个股票“弹性”动画。
答案 1 :(得分:14)
transform.scale
,有人吗?
let anim = CAKeyframeAnimation(keyPath: "transform.scale")
anim.values = [0, 1, 0, 1, 0, 1, 0]
anim.duration = 4.0
smallView.layer.addAnimation(anim, forKey: "what")
完全无关,如果要在值数组中使用浮点数,则必须将它们添加为NSNumbers
,否则它们最终会以0结尾!
anim.values = [0.0, 1.2, 0.9, 1.0].map { NSNumber(double: $0) }
答案 2 :(得分:8)
您需要自己设置关键帧,而不是设置CAKeyframeAnimation的路径。我之前通过设置图层边界大小的动画来创建“弹出”效果:
CAKeyframeAnimation *boundsOvershootAnimation = [CAKeyframeAnimation animationWithKeyPath:@"bounds.size"];
CGSize startingSize = CGSizeZero;
CGSize overshootSize = CGSizeMake(targetSize.width * (1.0f + POPINOVERSHOOTPERCENTAGE), targetSize.height * (1.0f + POPINOVERSHOOTPERCENTAGE));
CGSize undershootSize = CGSizeMake(targetSize.width * (1.0f - POPINOVERSHOOTPERCENTAGE), targetSize.height * (1.0f - POPINOVERSHOOTPERCENTAGE));
NSArray *boundsValues = [NSArray arrayWithObjects:[NSValue valueWithCGSize:startingSize],
[NSValue valueWithCGSize:overshootSize],
[NSValue valueWithCGSize:undershootSize],
[NSValue valueWithCGSize:targetSize], nil];
[boundsOvershootAnimation setValues:boundsValues];
NSArray *times = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:0.5f],
[NSNumber numberWithFloat:0.9f],
[NSNumber numberWithFloat:1.0f], nil];
[boundsOvershootAnimation setKeyTimes:times];
NSArray *timingFunctions = [NSArray arrayWithObjects:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
nil];
[boundsOvershootAnimation setTimingFunctions:timingFunctions];
boundsOvershootAnimation.fillMode = kCAFillModeForwards;
boundsOvershootAnimation.removedOnCompletion = NO;
其中,POPINOVERSHOOTPERCENTAGE是我想要超出图层目标尺寸的部分。
答案 3 :(得分:5)
我不知道你是否可以使用CAKeyframeAnimation来动画UIView的比例,但你可以使用CABasicAnimation并设置fromValue和toValue属性,并使用它来为transform属性设置动画:
- (CAAnimation*)monInAnimation
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(3.0, 3.0, 3.0)];
[animation setDuration:1.5];
[animation setAutoreverses:YES];
return animation;
}
- (IBAction)monBtnIn
{
[monButton.layer addAnimation:[self monInAnimation] forKey:@"transform"];
}