Как вы оцениваете масштаб CAKeyframeAnimation?
Я хочу создать анимацию с несколькими ключевыми кадрами. Мне нужен мой слой (кнопка в этом случае)
для масштабирования до 1,5, затем до 0,5, затем до 1,2, затем до 0,8 и 1,0.
Я также хочу EaseIn и EaseOut каждого ключевого кадра.
Как вы можете себе представить, это создаст эффект Springy/Bounce на месте.
В других частях моего приложения я использовал 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"];
}
Ответы
Ответ 1
Два альтернативных решения для вас:
Во-первых, вы также можете анимировать свойство transform.
Использование кода Brad, но с помощью @ "transform" для ключевого пути. Основное преимущество заключается в том, что вам не нужно вычислять фактический кадр, а вместо этого обеспечить простой коэффициент масштабирования:
Objective-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, оболочку с открытым исходным кодом для основной анимации. Он включает в себя запатентованную "пружинную" анимацию.
Вы можете получить его по адресу:
http://github.com/neror/ftutils
Ответ 2
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")
Полностью не связанный, если вы собираетесь использовать float в массиве значений, вы должны добавить их как NSNumbers
, иначе они просто закончили бы как 0s!
anim.values = [0.0, 1.2, 0.9, 1.0].map { NSNumber(double: $0) }
Ответ 3
Вместо того, чтобы устанавливать путь к вашей CAKeyframeAnimation, вам нужно будет установить ключевые кадры. Я создал эффект "pop-in" раньше, анимируя размер границ слоя:
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 - это доля, с которой я хотел превысить целевой размер слоя.
Ответ 4
Я не знаю, можете ли вы использовать 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"];
}