实际开发中一个物体的运动往往是复合运动,单一属性的运动情况比较少,但是属性动画每次只能设置一个属性进行动画控制(不管是基础动画还是关键帧动画都是如此),这样一来要做一个复合运动的动画就必须创建多个属性动画进行组合。对于一两种动画的组合或许处理起来还比较容易,但是对于更多动画的组合控制往往会变得很麻烦,动画组的产生就是基于这样一种情况而产生的。动画组是一系列动画的组合,凡是添加到动画组中的动画都受控于动画组,这样一来各类动画公共的行为就可以统一进行控制而不必单独设置,而且放到动画组中的各个动画可以并发执行,共同构建出复杂的动画效果。
动画组使用起来并不复杂,首先单独创建单个动画(可以是基础动画也可以是关键帧动画),然后将基础动画添加到动画组,最后将动画组添加到图层即可。
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
@interface ViewController () <CAAnimationDelegate>
@property (nonatomic, strong) CALayer *animationCALayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.animationCALayer = [[CALayer alloc] init];
self.animationCALayer.bounds = CGRectMake(0, 0, 40, 40);
self.animationCALayer.position = CGPointMake(150, 150);
self.animationCALayer.contents = (id)[UIImage imageNamed:@"vehicleResource.png"].CGImage;
[self.view.layer addSublayer:self.animationCALayer];
//创建动画
[self groupAnimation];
}
#pragma mark - 关键帧动画
- (CAKeyframeAnimation *) translationAnimation {
// 1、创建关键帧动画并设置动画属性
CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 2、设置路径
// 绘制贝塞尔曲线
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, self.animationCALayer.position.x, self.animationCALayer.position.y); // 移动到起始点
CGPathAddCurveToPoint(path, NULL, -50.0, 200.0, 150.0, 300.0,100.0, 500.0); // 绘制二次贝塞尔曲线
keyframeAnimation.path = path; // 设置path属性
CGPathRelease(path); // 释放路径对象
[keyframeAnimation setValue:[NSValue valueWithCGPoint:CGPointMake(100, 500)] forKey:@"KCKeyframeAnimationProperty_EndPosition"];
// 3、添加动画到图层,添加动画后就会执行动画
return keyframeAnimation;
}
#pragma mark - 旋转动画
- (CABasicAnimation *) rotationAnimation {
// 1、创建动画并指定动画属性
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
// 2、设置动画属性初始值、结束值
// basicAnimation.fromValue = [NSNumber numberWithInt:M_PI_2];
basicAnimation.toValue = [NSNumber numberWithFloat:M_PI_2*3];
//设置其他动画属性
basicAnimation.duration = 6.0;
basicAnimation.autoreverses = false; // 旋转后再旋转到原来的位置
[basicAnimation setValue:[NSNumber numberWithFloat:M_PI_2*3] forKey:@"KCBasicAnimationProperty_ToValue"];
return basicAnimation;
}
#pragma mark 创建动画组
-(void)groupAnimation{
//1.创建动画组
CAAnimationGroup *animationGroup=[CAAnimationGroup animation];
//2.设置组中的动画和其他属性
CABasicAnimation *basicAnimation = [self rotationAnimation];
CAKeyframeAnimation *keyframeAnimation = [self translationAnimation];
animationGroup.animations = @[basicAnimation, keyframeAnimation];
animationGroup.delegate = self;
animationGroup.duration = 6.0;//设置动画时间,如果动画组中动画已经设置过动画属性则不再生效
animationGroup.beginTime = CACurrentMediaTime() + 10;//延迟五秒执行
//3.给图层添加动画
[self.animationCALayer addAnimation:animationGroup forKey:nil];
}
#pragma mark - 代理方法
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
CAAnimationGroup *animationGroup = (CAAnimationGroup *)anim;
CABasicAnimation *basicAnimation = (CABasicAnimation *)animationGroup.animations[0];
CAKeyframeAnimation *keyframeAnimation = (CAKeyframeAnimation *)animationGroup.animations[1];
CGFloat toValue = [[basicAnimation valueForKey:@"KCBasicAnimationProperty_ToValue"] floatValue];
CGPoint endPoint = [[keyframeAnimation valueForKey:@"KCKeyframeAnimationProperty_EndPosition"] CGPointValue];
[CATransaction begin];
[CATransaction setDisableActions:YES];
//设置动画最终状态
self.animationCALayer.position = endPoint;
self.animationCALayer.transform = CATransform3DMakeRotation(toValue, 0, 0, 1);
[CATransaction commit];
}