一、简介
iOS动画主要是指Core Animation框架。官方使用文档地址为:Core Animation Guide。Core Animation是iOS和macOS平台上负责图形渲染与动画的基础框架。Core Animation可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作。你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用Core Animation的动画效果。Core Animation将大部分实际的绘图任务交给了图形硬件来处理,图形硬件会加速图形渲染的速度。这种自动化的图形加速技术让动画拥有更高的帧率并且显示效果更加平滑,不会加重CPU的负担而影响程序的运行速度。
乔帮主在2007年的WWDC大会上亲自为你演示Core Animation的强大:点击查看视频
二.iOS动画的调用方式
第一种调用方式:
_demoView.frame = CGRectMake(0, SCREEN_HEIGHT/2-50, 50, 50);
[UIView animateWithDuration:1.0f animations:^{
_demoView.frame = CGRectMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50, 50, 50);
} completion:^(BOOL finished) {
_demoView.frame = CGRectMake(SCREEN_WIDTH/2-25, SCREEN_HEIGHT/2-50, 50, 50);
}];
第二种:UIView [begin commit]模式(首尾式)
_demoView.frame = CGRectMake(0, SCREEN_HEIGHT/2-50, 50, 50);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0f];
_demoView.frame = CGRectMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50, 50, 50);
[UIView commitAnimations];
其中最为有价值的是一个叫动画组的概念是进行UIimageView的帧动画
// 1.3把数组存入UIImageView中
self.animationImageView.animationImages = array;
// 1.4 option
self.animationImageView.animationRepeatCount = 1;
// fps 12
self.animationImageView.animationDuration = frames / 12;
// 1.5播放动画
[self.animationImageView startAnimating];
// self.animationImageView.animationImages = nil;
[self.animationImageView performSelector:@selector(setAnimationImages:) withObject:nil afterDelay:self.animationImageView.animationDuration];
demo2.gif
第三种调用动画方式- 核心动画
- 核心动画基本概念
- 基本动画
- 关键帧动画
- 动画组
- 转场动画
三.Core Animation简介
Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。
Core Animation可以用在Mac OS X和iOS平台。
Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
要注意的是,Core Animation是直接作用在CALayer上的,并非UIView
一.核心动画继承结构
image.png二.Core Animation的使用步骤
开发步骤:
1.首先得有CALayer
2.初始化一个CAAnimation对象,并设置一些动画相关属性
3.通过调用CALayer的addAnimation:forKey:方法,增加CAAnimation对象到CALayer中,这样就能开始执行动画了
4.通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画
三.CAAnimation——简介
是所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类
属性说明:(红色代表来自CAMediaTiming协议的属性)
- duration:动画的持续时间
- repeatCount:重复次数,无限循环可以设置HUGE_VALF或者MAXFLOAT
- repeatDuration:重复时间
- removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行
后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards - fillMode:决定当前对象在非active时间段的行为。比如动画开始之前或者动画结束之后
- beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为-
CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间 - timingFunction:速度控制函数,控制动画运行的节奏
- delegate:动画代理
四.CAAnimation——动画填充模式
fillMode属性值(要想fillMode有效,最好设置removedOnCompletion = NO)
- kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
- kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
- kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。
- kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态
五.CAAnimation——速度控制函数
速度控制函数(CAMediaTimingFunction)
- kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉
- kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开
- kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
- kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。
六.CALayer上动画的暂停和恢复
#pragma mark 暂停CALayer的动画
-(void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
// 让CALayer的时间停止走动
layer.speed = 0.0;
// 让CALayer的时间停留在pausedTime这个时刻
layer.timeOffset = pausedTime;
}
CALayer上动画的恢复
#pragma mark 恢复CALayer的动画
-(void)resumeLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = layer.timeOffset;
// 1. 让CALayer的时间继续行走
layer.speed = 1.0;
// 2. 取消上次记录的停留时刻
layer.timeOffset = 0.0;
// 3. 取消上次设置的时间
layer.beginTime = 0.0;
// 4. 计算暂停的时间(这里也可以用CACurrentMediaTime()-pausedTime)
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
// 5. 设置相对于父坐标系的开始时间(往后退timeSincePause)
layer.beginTime = timeSincePause;
}
七.CAPropertyAnimation
是CAAnimation的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:
CABasicAnimation
CAKeyframeAnimation
属性说明:
- keyPath:通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@“position”为keyPath,就修改CALayer的position属性的值,以达到平移的动画效果
八.CABasicAnimation——基本动画
基本动画,是CAPropertyAnimation的子类
属性说明:
- fromValue:keyPath相应属性的初始值
- toValue:keyPath相应属性的结束值
动画过程说明:
- 随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue
- keyPath内容是CALayer的可动画Animatable属性
- 如果fillMode=kCAFillModeForwards同时removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。
九.CAKeyframeAnimation——关键帧动画
- 关键帧动画,也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:
CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值
属性说明:
- values:上述的NSArray对象。里面的元素称为“关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
- path:可以设置一个CGPathRef、CGMutablePathRef,让图层按照路径轨迹移动。path只对CALayer的anchorPoint和position起作用。如果设置了path,那么values将被忽略
- keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,-
![Uploading keyframeAnimation_390929.gif . . .]
keyTimes中的每一个时间值都对应values中的每一帧。如果没有设置keyTimes,各个关键帧的时间是平分的
CABasicAnimation可看做是只有2个关键帧的CAKeyframeAnimation
keyframeAnimation.gif十.CAAnimationGroup——动画组
- 动画组,是CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行
属性说明:
- animations:用来保存一组动画对象的NSArray
- 默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的-
beginTime属性来更改动画的开始时间
十一.转场动画——CATransition
- CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点
- UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果
- 动画属性:
- type:动画过渡类型
- subtype:动画过渡方向
- startProgress:动画起点(在整体动画的百分比)
- endProgress:动画终点(在整体动画的百分比)
subtype:动画过渡方向
kCATransitionFromRight 从右侧进入
kCATransitionFromLeft 从左侧进入
kCATransitionFromTop 从顶部进入
kCATransitionFromBottom 从底部进入
startProgress:动画起点(在整体动画的百分比)
endProgress:动画终点(在整体动画的百分比)
transition.gif
image.png
Apple 官方的SDK其实只提供了四种过渡效果。
- kCATransitionFade 渐变效果
- kCATransitionMoveIn 进入覆盖效果
- kCATransitionPush 推出效果
- kCATransitionReveal 揭露离开效果
注意点 - 私有api,不建议开发者们使用。因为苹果公司不提供维护,并且有可能造成你的app审核不通过。
四.使用UIView动画函数实现转场动画
单视图
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;
参数说明:
- duration:动画的持续时间
- view:需要进行转场动画的视图
- options:转场动画的类型
- animations:将改变视图属性的代码放在这个block中
- completion:动画结束后,会自动调用这个block
双视图
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion;
参数说明:
- duration:动画的持续时间
- options:转场动画的类型
- animations:将改变视图属性的代码放在这个block中
- completion:动画结束后,会自动调用这个block
五.粒子动画
粒子动画.gif在iOS 5中,苹果引入了一个新的CALayer子类叫做CAEmitterLayer。CAEmitterLayer是一个高性能的粒子引擎,被用来创建实时例子动画如:烟雾,火,雨等等这些效果。
CAEmitterLayer看上去像是许多CAEmitterCell的容器,这些CAEmitierCell定义了一个例子效果。你将会为不同的例子效果定义一个或多个CAEmitterCell作为模版,同时CAEmitterLayer负责基于这些模版实例化一个粒子流。一个CAEmitterCell类似于一个CALayer:它有一个contents属性可以定义为一个CGImage,另外还有一些可设置属性控制着表现和行为。
在iOS中实现粒子特效,有对应的的属性CAEmitterLayer,它是Layer的子类,用它来实现粒子特效不会怎么占用资源,从而去影响UI的流程性。
粒子CAEmitterLayer发射器的基本属性
我来举个通俗易懂的例子吧CAEmitterLayer就像大炮,决定了(1)哪里发射(2)大炮有多大CAEmitterCell就像是炮弹,觉得了(1)初速度(2)加速度(3)炮弹类型(4)发射后的角度 等等
粒子CAEmitterLayer发射器的基本属性
//是否允许在规定的范围内
@property BOOL masksToBounds;
//发射器的形状
//kCAEmitterLayerPoint 点的形状,粒子从一个点发出
//kCAEmitterLayerLine 线的形状,粒子从一条线发出
//kCAEmitterLayerRectangle 矩形形状,粒子从一个矩形中发出
//kCAEmitterLayerCuboid 立方体形状,会影响z平面的效果
//kCAEmitterLayerCircle 圆形,粒子会在圆形范围发射
//kCAEmitterLayerSphere 球形
@property(copy) NSString *emitterShape;
//发射器的发射模式
//kCAEmitterLayerPoints 从发射器中发出
//kCAEmitterLayerOutline 从发射器边缘发出
//kCAEmitterLayerSurface 从发射器表面发出
//kCAEmitterLayerVolumen 从发射器中点发出
@property(copy) NSString *emitterMode;
// 发射器的尺寸大小
@property CGSize emitterSize;
//发射器在xy平面的中心位置
@property CGPoint emitterPosition;
//发射器在Z平面的位置
@property CGFloat emitterZPosition;
粒子的属性,也就是特效,需要用到CAEmitterCell这个类
//类方法创建发射单元
+ (instancetype)emitterCell;
//粒子的创建速率
@property float birthRate;
//粒子的生存时间
@property float lifetime;
//粒子的生存时间容差
@property float lifetimeRange;
//粒子在Z轴方向的发射角度
@property CGFloat emissionLatitude;
//粒子在xy平面的发射角度
@property CGFloat emissionLongitude;
//粒子发射角度的容差
@property CGFloat emissionRange;
//粒子的速度
@property CGFloat velocity;
//粒子速度的容差
@property CGFloat velocityRange;
//x,y,z三个方向的加速度
@property CGFloat xAcceleration;
@property CGFloat yAcceleration;
@property CGFloat zAcceleration;
//缩放大小,缩放容差和缩放速度
@property CGFloat scale;
@property CGFloat scaleRange;
@property CGFloat scaleSpeed;
//旋转度与旋转容差
@property CGFloat spin;
@property CGFloat spinRange;
@property CGColorRef color;\
//粒子在rgb三个色相上的容差和透明度的容差
@property float redRange;
@property float greenRange;
@property float blueRange;
@property float alphaRange;
//粒子在RGB三个色相上的变化速度和透明度的变化速度
@property float redSpeed;
@property float greenSpeed;
@property float blueSpeed;
@property float alphaSpeed;
//渲染粒子,可以设置为一个CGImage的对象
@property(strong) id contents;
//渲染的范围
@property CGRect contentsRect;
代码使用
使用:
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)setup {
self.emitterLayer.masksToBounds = YES;
self.emitterLayer.emitterShape = kCAEmitterLayerLine;
self.emitterLayer.emitterMode = kCAEmitterLayerSurface;
self.emitterLayer.emitterSize = self.frame.size;
self.emitterLayer.emitterPosition
= CGPointMake(self.bounds.size.width / 2.f, -20);
}
- (void)show {
CAEmitterCell *rainFlake = [CAEmitterCell emitterCell];
rainFlake.birthRate = 25.f;
rainFlake.speed = 10.f;
rainFlake.velocity = 10.f;
rainFlake.velocityRange = 10.f;
rainFlake.yAcceleration = 1000.f;
rainFlake.contents = (__bridge id _Nullable)([UIImage imageNamed:@"234"].CGImage);
rainFlake.color = [UIColor blackColor].CGColor;
rainFlake.lifetime = 7.f;
rainFlake.scaleRange = 0.f;
rainFlake.scale = 0.2f;
//添加动画
self.emitterLayer.emitterCells = @[rainFlake];
}
效果展示
下雨.gif ![星星.gif](http:https://img.haomeiwen.com/i1170421/57934d29912e713c.gif?imageMogr2/auto-orient/strip)六.第三方框架-POP框架
image.pngPOP是一个在iOS与OS X上通用的极具扩展性的动画引擎。它在基本的静态动画的基础上增加的弹簧动画与衰减动画,使之能创造出更真实更具物理性的交互动画。POP的API可以快速的与现有的ObjC代码集成并可以作用于任意对象的任意属性。POP是个相当成熟且久经考验的框架,Facebook出品的令人惊叹的Paper应用中的所有动画和效果即出自POP。
pop弹簧效果.gif使用
POP默认支持三种动画,但同时也支持自定义动画。
• POPBasicAnimation
• POPSpringAnimation
• POPDecayAnimation
• POPCustomAnimation //自定义动画
1. POPBasicAnimation使用最广泛 提供固定时间间隔的动画(如淡入淡出效果)
//基础动画
UIView *baseAnimation = [[UIView alloc]init];
baseAnimation.backgroundColor = [UIColor yellowColor];
baseAnimation.frame = CGRectMake(0, 0, 100, 100);
baseAnimation.center = self.view.center;
[self.view addSubview:baseAnimation];
//设置动画
POPBasicAnimation *popBaseAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPosition];
popBaseAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(baseAnimation.center.x, 400)];
popBaseAnimation.duration = 3.f;
popBaseAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[baseAnimation.layer pop_addAnimation:popBaseAnimation forKey:nil];
self.popView = baseAnimation;
popBaseAnimation.gif
可以看到,添加一个动画最少仅需三步
1. 定义一个animation对象,并指定对应的动画属性
2. 设置初始值和默认值(初始值可以不指定,会默认从当前值开始)
3. 添加到想产生动画的对象上
2.POPSpringAnimation
POPSpringAnimation也许是大多数人使用POP的理由,其提供一个类似弹簧一般的动画效果.
UIView *springAnimation = [[UIView alloc]init];
springAnimation.backgroundColor = [UIColor blueColor];
springAnimation.frame = CGRectMake(0, 0, 100, 100);
springAnimation.center = self.view.center;
[self.view addSubview:springAnimation];
POPSpringAnimation *popSpringAnimation = \
[POPSpringAnimation animationWithPropertyNamed:kPOPViewBounds];
popSpringAnimation.springSpeed = 0;
popSpringAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 300, 300)];
[springAnimation.layer pop_addAnimation:popSpringAnimation forKey:nil];
self.popView = springAnimation;
popSpringAnimation.gif
POPSpringAnimation可配置的属性与默认值为
- springBounciness:4.0 //[0-20] 弹力 越大则震动幅度越大
- springSpeed :12.0 //[0-20] 速度 越大则动画结束越快
- dynamicsTension :0 //拉力 接下来这三个都跟物理力学模拟相关 数值调整起来也很费时 没事不建议使用哈
- dynamicsFriction:0 //摩擦 同上
- dynamicsMass :0 //质量 同上
3.POPDecayAnimation
POPDecayAnimation提供一个过阻尼效果(其实Spring是一种欠阻尼效果),可以实现类似UIScrollView的滑动衰减效果
//添加一个减速动画
POPDecayAnimation *decayAnimation = \
[POPDecayAnimation animationWithPropertyNamed:kPOPLayerPosition];
//获取加速度
CGPoint velocity = [recognizer velocityInView:self.view];
decayAnimation.velocity = [NSValue valueWithCGPoint:velocity];
[recognizer.view.layer pop_addAnimation:decayAnimation forKey:nil];
popDecayAnimation.gif
注意:这里对POPDecayAnimation设置toValue是没有意义的,会被忽略(因为目的状态是动态计算得到的)
POPDecayAnimation可配置的属性与默认值为
- 注意:POPDecayAnimation也是没有duration字段的,其动画持续时间由velocity与deceleration决定
七.第三方框架 Lottie框架
什么是Lottie?
- 首先要说的是:什么是Lottie呢?由Airbnb开发的Lottie是一个将After Effects动画提供给任意一个iOS,macOS,Android还有React Native原生APP的文件库。这些动画通过一个叫Bodymovin的开源After Effects插件,以JSON文件的形式进行输出。Lottie通过JSON格式下载动画数据并实时提供给开发者。
换句话说,你也可以通过设计器直接把JSON文件放入Xcode project,让Lottie帮你下载动画。当然别误会,你还是需要为你的动画写一些代码,但是你会发现Lottie的确将为你的动画编码节省大量的时间。
Lottie 动画文件
在使用Lottie之前,你需要一个以JSON文件形式输出的动画数据库。如果你已经有了一个After Effects动画,用Bodymovin插件来创建JSON文件。
如果你不会使用After Effects呢?你要如何准备你的动画?你可以雇一位设计师为你设计动画,或者你学会用After Effects。
幸运的是,这里还有一个选项,那就是:Lottie Files
用CocoaPods安装Lottie动画库
当你创建完项目,离开Xcode,打开Terminal。我们将为安装Lottie动画库创建一个Podfile。我想你应该已经有一些使用CocoaPods的经验并且已经把它安装在你的电脑中了。
在terminal中运行下列指令来创建一个Podfile。
/**
lottie动画展示
*/
- (void)playAnimationWithName: (NSString *)name {
NSString *path = [[NSBundle mainBundle]pathForResource:name ofType:nil ];
LOTAnimationView *lotAnimation = [LOTAnimationView animationWithFilePath:path];
lotAnimation.frame = CGRectMake(0, 0, 400, 400);
lotAnimation.center = self.view.center;
lotAnimation.contentMode = UIViewContentModeScaleAspectFill;
[self.view addSubview:lotAnimation];
[lotAnimation play];
lotAnimation.loopAnimation = YES;
self.lotAnimation = lotAnimation;
}
demo展示
lottieAnimation.gif本篇动画作为自己的总结.其中引用大量的博主的动画文章.没有任何商业用途.都是用于学习跟总结回头.诸君共勉!!!
以下为本文的出入跟资料:
1.使用带粒子效果的 CAEmitterLayer视频教学
2.POP基础动画视频教学
3.Lottie简介 & iOS集成使用
4.Lottie初级教程:打造iOS APP完美动画
5.iOS动画(Core Animation)总结
6.M了个J - Core Animation1-简介
7.iOS中粒子发射(封装下雨,下雪,喷火等特效)
8.iOS那些简单的动画(不定期更新)
9iOS动画之用CAEmitterLayer实现炫酷的动画
10动画demo大综合github社区
网友评论