Core Animation

CoreAnimation是iOS与OS X平台上负责图形渲染与动画的基础设施。Core Animation可以动画视图和其他的可视元素,为你完成了动画所需的大部分绘帧工作。只需配置少量的动画参数(如开始点位置和结束点的位置)就可实现绚丽的Core Animation动画效果。

Core Animation将大部分实际的绘图任务交给了图形硬件来处理,图形硬件会加速图形渲染的速度。这种自动化的图形加速技术让动画拥有更高的帧率并且更加的平滑,而且不会加重CPU的负担而影响程序的运行速度。

Core Animation自身并不是一个绘图系统。它只是一个负责在硬件上合成和操纵应用内容的基础构件。Core Animation的核心是图层对象,图层对象用于管理和操控你的应用内容。图层将捕获的内容放到一副位图中,图形硬件能够非常容易的操控你的位图。

当我们平时使用UIView动画不能满足需求的时候,可以直接对UIView的内容绘制的layer进行操作,Core Animation是UIview动画底层的实现,是对CALayer进行操作,所以Core Animation操作的对象是CALayer,而不是UIView。

Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程(执行动画的时候还能点击UI其它控件触发别的事件)。

Image text

CAAnimation:核心动画的基础类,不能直接使用,负责动画运行时间、速度的控制,本身实现了CAMediaTiming协议
CAPropertyAnimation:属性动画的基类(通过属性进行动画设置,注意是可动画属性),不能直接使用

CABasicAnimation:基本动画,通过属性修改进行动画参数控制,只有初始状态和结束状态
CAKeyframeAnimation:关键帧动画,同样是通过属性进行动画参数控制,但是同基础动画不同的是它可以有多个状态控制
CAAnimationGroup:动画组,动画组是一种组合模式设计,可以通过动画组来进行所有动画行为的统一控制,组中所有动画效果可以并发执行
CATransition:转场动画,主要通过滤镜进行动画效果设置

一、CABasicAnimation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CABasicAnimation *anim = [CABasicAnimation animation];
// 通过keyPath来告诉layer要执行怎样的动画(旋转,平移,缩放),该属性必须是layer的一个属性
anim.keyPath = @"transform.scale.x";
// anim.keyPath = @"transform.rotation.z";
// anim.keyPath = @"position"; // anim.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
// anim.keyPath = @"bounds"; // anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 250, 250)];
// anim.keyPath = @"transform"; // anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_4, 0, 0, 1)];
anim.fromValue = @(4);
anim.toValue = @(1.5);
// 还可以设置成颜色变化
// anim.toValue = (id)[UIColor redColor].CGColor;
// 动画结束后不要移除动画效果
anim.removedOnCompletion = NO;
// 保持动画执行后的状态
anim.fillMode = kCAFillModeBoth;
// 设置动画的执行时间 (当前动画时间 + 延迟2s执行)
anim.beginTime = CACurrentMediaTime() + 2;
[self.blueView.layer addAnimation:anim forKey:nil];

二、CAKeyframeAnimation

1、做一个抖动效果

1
2
3
4
5
6
7
8
9
// 角度转换弧度的宏
#define angle2Radian(angel) ((angel) * M_PI / 180.0)
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
anim.values = @[@(angle2Radian(-3)),@(angle2Radian(3)),@(angle2Radian(-3))];
anim.repeatCount = MAXFLOAT;
anim.duration = 0.2f;
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
[self.redView.layer addAnimation:anim forKey:@"abc"];

2、设置关键帧数组values

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 设置关键帧
anim.values = @[[NSValue valueWithCGPoint:CGPointZero],
[NSValue valueWithCGPoint:CGPointMake(200, 0)],
[NSValue valueWithCGPoint:CGPointMake(200, 200)],
[NSValue valueWithCGPoint:CGPointMake(0, 200)],
[NSValue valueWithCGPoint:CGPointZero]];
// 设置关键帧执行的时间点(每一个元素的取值范围是0到1,后面的值要大于前面的值)
anim.keyTimes = @[@(0),@(0.1),@(0.5),@(0.8),@(1)];
anim.duration = 2.0f;
// 保持动画执行完毕的状态
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
// 设置动画执行节奏
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[self.redView.layer addAnimation:anim forKey:nil];

3、设置路径path

1
2
3
4
5
6
7
8
9
10
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 创建一个圆圈路径
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, CGRectMake(100, 100, 250,250));
anim.path = path;
anim.duration = 2.0f;
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[self.redView.layer addAnimation:anim forKey:nil];

三、CAAnimationGroup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
CAKeyframeAnimation *position = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 创建路径
CGMutablePathRef path = CGPathCreateMutable();
// 起始
CGPathMoveToPoint(path, NULL, startPoint.x, startPoint.y);
// 创建关键控制点数组(数组存放CGRect, CGRect的x、y值作为控制点xy坐标值,width和height作为结束点的xy坐标值)
NSMutableArray *pointArrs = [[NSMutableArray alloc] init];
CGFloat width = [UIScreen mainScreen].bounds.size.width / 2;
[pointArrs addObject:NSStringFromCGRect(CGRectMake(width, 300, width, 300))];
[pointArrs addObject:NSStringFromCGRect(CGRectMake(width, 300, width, 300))];
[pointArrs enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
CGRect rect = CGRectFromString(obj);
// 二阶贝塞尔曲线
CGPathAddQuadCurveToPoint(path, NULL, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
}];
// 结束
CGPathAddQuadCurveToPoint(path, NULL, endPoint.x, endPoint.y, endPoint.x, endPoint.y);
position.path = path;
position.duration = 5.0;
position.speed = 0.7;
position.removedOnCompletion = NO;
position.fillMode = kCAFillModeForwards;
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.duration = 1.2;
scaleAnimation.beginTime = 0.f;
scaleAnimation.fromValue = [NSNumber numberWithFloat:0.7];
scaleAnimation.toValue = [NSNumber numberWithFloat:1.5];
scaleAnimation.removedOnCompletion = _removedOnCompletion;
scaleAnimation.fillMode = kCAFillModeForwards;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.duration = 5+3;
animationGroup.removedOnCompletion = NO;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.delegate = self;
animationGroup.animations = @[position,scaleAnimation];
[self.layer addAnimation:animationGroup forKey:@"SpecialGiftCar"];

四、CATransition

1
2
3
4
5
6
7
8
9
10
// 1.创建动画对象
CATransition *tran = [CATransition animation];
// 2.设置转场效果
tran.type = @"oglFlip";
// 3.设置转场方向
tran.subtype = kCATransitionFromRight;
NSString *imagename = [NSString stringWithFormat:@"%d",self.index];
self.imageView.image = [UIImage imageNamed:imagename];
// 4.添加动画到图层上
[self.imageView.layer addAnimation:tran forKey:nil];

附:过渡效果
fade //交叉淡化过渡(不支持过渡方向) kCATransitionFade
push //新视图把旧视图推出去 kCATransitionPush
moveIn //新视图移到旧视图上面 kCATransitionMoveIn
reveal //将旧视图移开,显示下面的新视图 kCATransitionReveal

/**下面几个也是过渡效果,但它们是私有API效果,使用的时候要小心,可能会导致app审核不被通过*/
cube //立方体翻滚效果
oglFlip //上下左右翻转效果
suckEffect //收缩效果,如一块布被抽走(不支持过渡方向)
rippleEffect //滴水效果(不支持过渡方向)
pageCurl //向上翻页效果
pageUnCurl //向下翻页效果
cameraIrisHollowOpen //相机镜头打开效果(不支持过渡方向)
cameraIrisHollowClose //相机镜头关上效果(不支持过渡方向)

打赏支持一下呗!