demo 地址
內容
- 關于圖層動畫相關框架的介紹
- CoreAnimation結構及圖層動畫
- 簡單demo使用
1. CoreGraphics,QuartzCore, CoreAnimation區別
對CoreGraphics,QuartzCore, CoreAnimation 這三個概念傻傻分不清,先梳理一下
CoreGraphics(核心圖形)
它是iOS的核心圖形庫,包含Quartz2D繪圖API接口,常用的是point,size,rect等這些圖形,都定義在這個框架中,類名以CG開頭的都屬于CoreGraphics框架,它提供的都是C語言函數接口,是可以在iOS和mac OS 通用的
QuartzCore
Quartz是位于Mac OS X的Drawin核心之上的繪圖層,這個框架感覺不是很清晰,但是看頭文件可以發現,它就是CoreAnimation,這個框架頭文件只包含了CoreAnimation.h
CoreAnimation(核心動畫)
- CoreAnimation翻譯過來就是核心動畫,一組非常強大的API,用來做動畫的,非常的簡單,但是效果非常絢麗
- CoreAnimation是跨平臺的,既可以支持IOS,也支持MAC OS
- CoreAnimation執行動畫是在后臺,不會阻塞主線程
- CoreAnimation作用在CALayer,不是UIView
-
CoreGraphics和CoreAnimation的關系
首先它們都是跨iOS和Mac OS 使用的,這點區別于UIKit,并且CoreAnimation中大量使用到CoreGraphics中的類,因為實現動畫要用到圖形庫中的定西
-
為什么CA神馬神馬的,用的時候好多都要“.CGXXXX”呢?
比如 :
layer.backgroundColor = [UIColor redColor].CGColor;首先,CALayer是定義在QuartzCore框架中的,CGImageRef、CGColorRef兩種數據類型是定義在CoreGraphics框 架中的,而UIColor和UIImage是定義在UIKit框架中的。
其次,QuartzCore框架和CoreGraphics框架是可以跨平臺使用的,在iOS和Mac OS X上都能使用
但是UIKit只能在iOS中使用。所以,為了保證可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef。
框架關系
- 可以看出,CoreGraphics是底層繪制框架,我們實際會用到的也就是CG開頭的一些底層繪制函數和變量,這是一個純C語言框架
- QuartzCore(包含CoreAnimation)框架,是iOS系統的基本渲染框架,是一個OC語言框架,是一套基于CoreGraphics的OC語言封裝,封裝出了基本渲染類CALayer
2.CoreAnimation結構及圖層動畫 官方文檔
核心動畫類結構
- CALayer 圖層類
- CAAnimation 動畫計時類
- CAAnimationGroup 是個動畫組,可以同時進行縮放,旋轉
- CAPropertyAnimation 也是個抽象類,本身不具備動畫效果,只有子類才有。
- CATransition 轉場動畫,界面之間跳轉(切換)
- CAConstraint 布局約束類
- CATransaction 事物類,可以同時設置多個layer層的動畫效果。可以通過隱式和顯式兩種方式來進行動畫操作
2.1 關于圖層
CALayer基本屬性
@property CGRect bounds; //寬度和高度
@property CGPoint position; //位置(默認指中點,具體由anchorPoint決定)
@property CGPoint anchorPoint; // 錨點(x,y的范圍都是0-1),決定了position的位置
@property CGColorRef backgroundColor; // 背景顏色(CGColorRef類型)
@property CATransform3D transform; //形變屬性
可動畫屬性特點:
* 直接對它付值可產生隱士動畫
* CAAnimation的keyPath可以設置為這個屬性的名字
對這些屬性賦值的時候,layer會讓它的delegate調用actionForLayer:forKey:方法獲取一個返回值,這個返回值可能是這樣幾種情況:
1、是一個nil,則layer會走自己的隱式動畫;
2、是一個NSNull,則layer不會做任何動畫;
3、是一個實現了CAAction協議的對象,則layer會用這個對象生成一個CABasicAnimation加到自己身上執行動畫
CALayer與UIView的關系
-
UIView之所以能顯示在屏幕上,完全是因為它內部的一個圖層:
在創建UIView對象時,UIView內部會自動創建一個圖層(即CALayer對象),通過UIView的layer屬性可以訪問這個層。
@property(nonatomic,readonly,retain) CALayer *layer;
當UIView需要顯示到屏幕上時,會調用drawRect:方法進行繪圖,并且會將所有內容繪制在自己的圖層上,繪圖完畢后, 系統會將圖層拷貝到屏幕上,于是就完成了UIView的顯示。
換句話說,UIView本身不具備顯示的功能,是它內部的層才有顯示功能。
對比CALayer,UIView多了一個事件處理的功能。也就是說,CALayer不能處理用戶的觸摸事件,而UIView可以
所以,如果顯示出來的東西需要跟用戶進行交互的話,用UIView;如果不需要跟用戶進行交互,用UIView或者CALayer都可以。當然,CALayer的性能會高一些,因為它少了事件處理的功能,更加輕量級
總結:CALayer作為一個跨平臺框架(OS X和iOS)QuatzCore的類,iOS系統
為了處理用戶交互事件(觸屏操作)用UIView封裝了一次CALayer,UIView本
身負責處理交互事件,其持有一個Layer,用來負責繪制這個View的內容。而
我們對UIView的和繪制相關的屬性賦值和訪問的時候(frame、
backgroundColor等)UIView實際上是直接調用其Layer對應的屬性(frame對
應frame,center對應position等)的getter和setter。
核心動畫渲染框架
- 圖層樹:包含每一層的對象模型值。他們就是你設定的圖層的屬性值
- 呈現樹:包含了當前動畫發生時候將要顯示的值(例如你要給圖層背景顏色設置新的值的時候,它會立即修改圖層樹里面相應的值。但是在呈現樹里面背景顏色值在將要顯示給用戶的時候才被更新為新值)
- 渲染樹:在渲染圖層的時候使用呈現樹的值 (渲染樹負責執行獨立于應用活動的復雜操作。渲染由一個單獨的進程或線程來執行,使其對應用程序的運行循環影響最小)
圖層幾何屬性(mac os 下坐標系)
- position:屬性是一個CGPoint值, 指定圖層相當于它父圖層的位置, 該值基于父圖層的坐標系
- bounds:屬性是CGRect值, 指定圖層的大小(bounds.size)和圖層的 原點(bounds.origin)
- anchorPoint:屬性是CGPoint值,anchorPoint指定了bounds相對于position的值,同時作為變換的支點,錨點使用單元空間坐標系表示,(0,0)接近圖層的原點,(1,1)原點的對角點。(當你設置圖層的 frame 屬性的時候,position 會根據錨點(anchorPoint)相應的改變,而當你設置圖層的 position 屬性的候,bounds 會根據錨點(anchorPoint)做相應的改變)
(錨點就是layer的那一個點在point上)
圖層的 frame、bounds、position 和 anchorPoint 關系如下圖所示
anchorPoint 默認值為(0.5,0.5),位于圖層的中心點。圖層的 position 值為(100.0,100.0),bounds 為(0.0,0.0,120,80.0)。通過計算得到圖層的 frame為(40.0,60.0,120.0,80.0)
幾種常用的Layer
-
CAEmitterLayer
CAEmitterLayer是CoreAnimation框架中的粒子發射層,博客中有詳細的介紹和范例,這里不再重復,地址如下:粒子效果的應用和火焰范例
-
CAGradientLayer
CAGradientLayer是用于色彩梯度展示的layer圖層,通過CAGradientLayer,我們可以很輕松的創建出有過渡效果的色彩圖
-
CAReplicatorLayer
CAReplocatorLayer是拷貝視圖容器,我們可以通過它,將其中的子layer進行拷貝,并進行一些差異處理
-
CAShapeLayer
CAShapeLayer是圖形layer層,我們可以自定義這個層的形狀
-
CATextLayer
CATextLayer可以進行文本的繪制
2.2 關于動畫
UIViewAnimation動畫
iOS開發中,UIKit為我們封裝好的核心動畫層的方法,通過這些方法,基本能達到我們項目的大多需求,其中UIView動畫使用簡便,開發中應用十分廣泛
- UIView動畫執行的兩種方式
- 使用begin和commit方式
例如:
UIView * view = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
[self.view addSubview:view];
view.backgroundColor=[UIColor redColor];
[UIView beginAnimations:@"test" context:nil];
[UIView setAnimationDuration:3];
view.backgroundColor=[UIColor orangeColor];
[UIView commitAnimations];//執行commit后,動畫即開始執行
```
2. 使用block塊api
例如:
[UIView animateWithDuration:1 animations:^{
_myView.alpha=0;
} completion:^(BOOL finished) {
if (finished) {
_myView.alpha=1;
}
}];
```
支持動畫的屬性
CAAnimation
如果你想更加自由的通過動畫操作視圖的屬性,你就需要跳過UIKit的封裝,使用CoreAnimation核心動畫層的方法來實現動畫,CoreAnimation能夠實現更多復雜、好看、高效的動畫效果
* 陰影,圓角,帶顏色的邊框。
* 3D變化。
* 透明遮罩
* 多級非線性動畫
CAAnimation是CoreAnimation框架中執行動畫的基類,是個抽象類,不具備動畫效果,必須用它的子類才有動畫效果,是所有動畫對象的父類,負責控制動畫的持續時間和速度
- 隱式動畫:不指定任何動畫類型,僅改變非根層layer(手動創建的layer)動畫屬性,coreAnimation會決定如何何時去做動畫,你不用做額外操作
- 顯式動畫:需要創建一個動畫對象,并設置開始和結束值,直到把動畫應用到某圖層上,動畫才開始執行
CAAnimation相關的幾個動畫類的關系圖
CAPropertyAnimation
是CAAnimation的子類,也是個抽象類,要想創建動畫對象,應該使用它的兩個子類:CABasicAnimation和CAKeyframeAnimation
- @property(nullable, copy) NSString *keyPath;
通過指定CALayer的一個屬性名稱為keyPath(NSString類型),并且對CALayer的這個屬性的值進行修改,達到相應的動畫效果
CABasicAnimation
基本動畫,通過設定起始點,終點,時間,動畫會沿著你這設定點進行移動,
隨著動畫的進行,在長度為duration的持續時間內,keyPath相應屬性的值從fromValue漸漸地變為toValue。
CAKeyframeAnimation
主要操作屬性有keyPath和values值組合,以通過設定CALayer的始點、中間關鍵點、終點的frame,時間,動畫會沿你設定的軌跡進行移動
與CABasicAnimation的區別是:
- CABasicAnimation只能從一個數值(fromValue)變到另一個數值(toValue),而CAKeyframeAnimation會使用一個NSArray保存這些數值
- CABasicAnimation可看做是只有2個關鍵幀的CAKeyframeAnimation
CAAnimationGroup
可以保存一組動畫對象,將CAAnimationGroup對象加入層后,組中所有動畫對象可以同時并發運行
CATransition
用于做轉場動畫,能夠為層提供移出屏幕和移入屏幕的動畫效果。iOS比Mac OS X的轉場動畫效果少一點。
UINavigationController就是通過CATransition實現了將控制器的視圖推入屏幕的動畫效果。
使用CoreAnimation做動畫的時候,遵循四步就好
1.創建CAAnmation子對象
2.設置CAAnmation的屬性
3.調用CALayer的addAnimation:forKey將CAAnimation對象添加到CALayer上,就能執行動畫
4.調用CALayer的removeAnimationForKey方法可以停止CALayer中的動畫
遺留問題
- 隱式動畫,顯式動畫和隱式事務,顯示事務混淆
- 沒有用到CATransaction begin,commit 依然有動畫效果
概念補充
顯式動畫&隱式動畫
- CALayer的動畫分為隱式動畫和顯式動畫,UIView內部關聯了一個CALayer,叫它“Root CALayer”.
- 所有的非Root CALayer的“Animatable”屬性在修改的時候會默認的產生隱式動畫
CATransaction 事務
CATransaction 是核心動畫里負責協調多個動畫更新顯示操作,保證多個動畫同時進行,用于配置隱式動畫,即CALayer屬性修改依賴CATransaction.
和動畫類似CATransaction也分為隱式事務和顯式事務
隱式事務:在某次RunLoop中設置了一個“Animatable”屬性,如果當前沒有設置事務,則會自動創建一個CATransaction,并在當前線程的下一個RunLoop中commit這個CATransaction
顯式事務:直接調用CATransaction的[CATransaction begin],[CATransaction commit]等相關方法
另外事務可以嵌套,當事務嵌套時候,只有最外層的事務commit了之后,整個動畫才會執行。