一、簡介
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];
第三種調用動畫方式- 核心動畫
- 核心動畫基本概念
- 基本動畫
- 關鍵幀動畫
- 動畫組
- 轉場動畫
三.Core Animation簡介
Core Animation,中文翻譯為核心動畫,它是一組非常強大的動畫處理API,使用它能做出非常炫麗的動畫效果,而且往往是事半功倍。也就是說,使用少量的代碼就可以實現非常強大的功能。
Core Animation可以用在Mac OS X和iOS平臺。
Core Animation的動畫執行過程都是在后臺操作的,不會阻塞主線程。
要注意的是,Core Animation是直接作用在CALayer上的,并非UIView
一.核心動畫繼承結構
二.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
十.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:動畫終點(在整體動畫的百分比)
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
五.粒子動畫
在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];
}
效果展示
六.第三方框架-POP框架
POP是一個在iOS與OS X上通用的極具擴展性的動畫引擎。它在基本的靜態動畫的基礎上增加的彈簧動畫與衰減動畫,使之能創造出更真實更具物理性的交互動畫。POP的API可以快速的與現有的ObjC代碼集成并可以作用于任意對象的任意屬性。POP是個相當成熟且久經考驗的框架,Facebook出品的令人驚嘆的Paper應用中的所有動畫和效果即出自POP。
使用
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;
可以看到,添加一個動畫最少僅需三步
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可配置的屬性與默認值為
- 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設置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展示
本篇動畫作為自己的總結.其中引用大量的博主的動畫文章.沒有任何商業用途.都是用于學習跟總結回頭.諸君共勉!!!
以下為本文的出入跟資料:
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社區