Core Animation

本文為讀書筆記: iOS Core Animation: Advanced Techniques
1.實際上layer才是真正用來在屏幕上顯示和做動畫,UIView僅僅是對它的一個封裝,提供了一些iOS類似于處理觸摸的具體功能,以及Core Animation底層方法的高級接口。

2.我們已經證實了圖層不能像視圖那樣處理觸摸事件,那么他能做哪些視圖不能做的呢?這里有一些UIView沒有暴露出來的CALayer的功能:

  • 陰影 、圓角、帶顏色的邊框
  • 3D變換
  • 非矩形范圍
  • 透明遮罩
  • 多級非線性動畫
CALayer 屬性 屬性類型 作用
contents id 設置圖片
contentsGravity NSString 設置圖片展示,類似于viewcontentMode

3.contents

id意味著給contents賦任何值編譯都可以通過,但是,在實踐中,如果你給contents賦的不是CGImage,那么你得到的圖層將是空白的。contents這個奇怪的表現是由Mac OS的歷史原因造成的。它之所以被定義為id類型,是因為在Mac OS系統上,這個屬性對CGImageNSImage類型的值都起作用。
使用 :layer.contents = (__bridge id)image.CGImage;

4.contentsGravity
UIViewcontentMode,對這些屬性的操作其實是對對應圖層的操作,contentsGravity就是圖層的contentMode


/** Layer `contentsGravity' values. **/

CA_EXTERN NSString * const kCAGravityCenter

CA_EXTERN NSString * const kCAGravityTop

CA_EXTERN NSString * const kCAGravityBottom

CA_EXTERN NSString * const kCAGravityLeft

CA_EXTERN NSString * const kCAGravityRight

CA_EXTERN NSString * const kCAGravityTopLeft

CA_EXTERN NSString * const kCAGravityTopRight

CA_EXTERN NSString * const kCAGravityBottomLeft

CA_EXTERN NSString * const kCAGravityBottomRight

CA_EXTERN NSString * const kCAGravityResize

CA_EXTERN NSString * const kCAGravityResizeAspect

CA_EXTERN NSString * const kCAGravityResizeAspectFill

5.contentsScale這個設置圖片的每個點1個像素或者兩個像素
使用 :
layer.contentsScale = image.scale;
或者
layer.contentsScale = [UIScreen mainScreen].scale;
6.contentsRect 可以用來作拼合圖片(一般APP估計不會使用)
7.CALayer給不同坐標系之間的圖層轉換提供了一些工具類方法:

- (CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer; 
- (CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer; 
- (CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer;
 - (CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;

8.陰影效果

  • shadowOpacity : 是一個必須在0.0(不可見)和1.0(完全不透明)之間的浮點數。
  • shadowColor : 屬性控制著陰影的顏色,和borderColorbackgroundColor一樣,它的類型也是CGColorRef。陰影默認是黑色。
  • shadowOffset屬性控制著陰影的方向和距離。它是一個CGSize的值,寬度控制這陰影橫向的位移,高度控制著縱向的位移。shadowOffset的默認值是 {0, -3},意即陰影相對于Y軸有3個點的向上位移(以為shadow最早出現在MacOS,在MacOS上坐標軸和iOS是相反的)。
  • shadowPath : 如果事先知道陰影的形狀,可以設置shadowPath來提高性能。

9.opacity相當于viewalpha

10.layer.shouldRasterize
這是由透明度的混合疊加造成的,當你顯示一個50%透明度的圖層時,圖層的每個像素都會一半顯示自己的顏色,另一半顯示圖層下面的顏色。這是正常的透明度的表現。但是如果圖層包含一個同樣顯示50%透明的子圖層時,你所看到的視圖,50%來自子視圖,25%來了圖層本身的顏色,另外的25%則來自背景色。
在我們的示例中,按鈕和表情都是白色背景。雖然他們都是50%的可見度,但是合起來的可見度是75%,所以標簽所在的區域看上去就沒有周圍的部分那么透明。所以看上去子視圖就高亮了,使得這個顯示效果都糟透了。
解決辦法:

bottomView.layer.shouldRasterize = YES;  
bottomView.layer.rasterizationScale = [UIScreen mainScreen].scale;

11.CGAffineTransform

  • 仿射的意思是無論變換矩陣用什么值,圖層中平行的兩條線在變換之后任然保持平行
  • 如果需要混合兩個已經存在的變換矩陣,就可以使用如下方法,在兩個變換的基礎上創建一個新的變換:
CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);

12.CATransform3Dm34元素,用來做透視
詳見

- (void)viewDidLoad {    [super viewDidLoad];  
  //create a new transform    
CATransform3D transform = CATransform3DIdentity;   
 //apply perspective  
  transform.m34 = - 1.0 / 500.0;  
  //rotate by 45 degrees along the Y axis  
  transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);   
 //apply to layer    
self.layerView.layer.transform = transform; }
  1. 創建一個3D的正方體](https://zsisme.gitbooks.io/ios-/content/chapter5/solid-objects.html))
    14.Core Graphics直接向原始的CALyer的內容中繪制一個路徑,相比直下,使用CAShapeLayer有以下一些優點:
  • 渲染快速。CAShapeLayer使用了硬件加速,繪制同一圖形會比用Core Graphics快很多。
  • 高效使用內存。一個CAShapeLayer不需要像普通CALayer一樣創建一個寄宿圖形,所以無論有多大,都不會占用太多的內存。
  • 不會被圖層邊界剪裁掉。一個CAShapeLayer可以在邊界之外繪制。你的圖層路徑不會像在使用Core Graphics的普通CALayer一樣被剪裁掉(如我們在第二章所見)。
  • 不會出現像素化。當你給CAShapeLayer做3D變換時,它不像一個有寄宿圖的普通圖層一樣變得像素化。

15.UILabel : 借助圖層代理直接將字符串使用Core Graphics寫入圖層的內容
16.宿主圖層 : 指的是viewlayer,既self.view.layer,可以通過下面的方法改變


+ (Class)layerClass

{

    return [CATextLayer class];

}

17.CATextLayer替換 UILabal](https://zsisme.gitbooks.io/ios-/content/chapter6/CATextLayer.html))

18.CATransformLayer :創建一個立方體圖層
19.CAGradientLayer

  • colors : 保存的各種顏色
  • locations : 顏色的作用范圍,這個范圍數組需要個顏色數組保持相同 , 當只有兩個顏色的時候設置gradientLayer.locations = @[@0,@1];是均分兩個視圖
  • startPoint,開始的點,(0 , 0)代表左上角
  • endPoint,結束的店,(1 , 1)代表右下角

20.CATiledLayer : 把一個大圖裁剪成小圖并加載,一般用在地圖,或者加載大的圖片.

  1. Transactions(事務) : 實際上是Core Animation用來包含一系列屬性動畫集合的機制,任何用指定事務去改變可以做動畫的圖層屬性都不會立刻發生變化,而是當事務一旦提交的時候開始用一個動畫過渡到新值。
  • begin : 開始
  • commit : 結束
  • + (void)setCompletionBlock:(nullable void (^)(void))block; : 代碼完成塊

例1

- (void)viewDidLoad

{

    [super viewDidLoad];    

    self.colorLayer = [CALayer layer];

    self.colorLayer.frame = CGRectMake(0.0f, 0.0f, 150.0f, 150.0f);

    self.colorLayer.backgroundColor = [UIColor blueColor].CGColor;

    //add it to our view

    [self.containerView.layer addSublayer:self.colorLayer];

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{
   //begin a new transaction

    [CATransaction begin];

    //set the animation duration to 1 second

    [CATransaction setAnimationDuration:5.0];

    //randomize the layer background color

    CGFloat red = arc4random() / (CGFloat)INT_MAX;

    CGFloat green = arc4random() / (CGFloat)INT_MAX;

    CGFloat blue = arc4random() / (CGFloat)INT_MAX;

    self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;

    //commit the transaction

    [CATransaction commit];

}

例2

- (void)viewDidLoad{    [super viewDidLoad];    //create sublayer    self.colorLayer = [CALayer layer];    self.colorLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);    self.colorLayer.backgroundColor = [UIColor blueColor].CGColor;    //add a custom action    CATransition *transition = [CATransition animation];    transition.type = kCATransitionPush;    transition.subtype = kCATransitionFromLeft;    self.colorLayer.actions = @{@"backgroundColor": transition};    //add it to our view    [self.layerView.layer addSublayer:self.colorLayer];}- (IBAction)changeColor{    //randomize the layer background color    CGFloat red = arc4random() / (CGFloat)INT_MAX;    CGFloat green = arc4random() / (CGFloat)INT_MAX;    CGFloat blue = arc4random() / (CGFloat)INT_MAX;    self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;}

22.隱式動畫是如何實現的

  • 圖層首先檢測它是否有委托,并且是否實現CALayerDelegate
    協議指定的-actionForLayer:forKey
    方法。如果有,直接調用并返回結果。
  • 如果沒有委托,或者委托沒有實現-actionForLayer:forKey
    方法,圖層接著檢查包含屬性名稱對應行為映射的actions
    字典。
  • 如果actions字典
    沒有包含對應的屬性,那么圖層接著在它的style
    字典接著搜索屬性名。
  • 最后,如果在style
    里面也找不到對應的行為,那么圖層將會直接調用定義了每個屬性的標準行為的-defaultActionForKey:
    方法。

23.CATransition響應CAAction協議,并且可以當做一個圖層行為.行為通常是一個被Core Animation隱式調用的顯式動畫對象。

24.presentationLayer : 呈現圖層 ,用戶真正看到的圖層(相當于View)
modelLayer : 圖層模型 (相當于Model)
Core Animation : 相當于控制器

大多數情況下,你不需要直接訪問呈現圖層,你可以通過和模型圖層的交互,來讓Core Animation更新顯示。兩種情況下呈現圖層會變得很有用,一個是同步動畫,一個是處理用戶交互。

  • 如果你在實現一個基于定時器的動畫(見第11章“基于定時器的動畫”),而不僅僅是基于事務的動畫,這個時候準確地知道在某一時刻圖層顯示在什么位置就會對正確擺放圖層很有用了。
  • 如果你想讓你做動畫的圖層響應用戶輸入,你可以使用-hitTest:方法(見第三章“圖層幾何學”)來判斷指定圖層是否被觸摸,這時候對呈現圖層而不是模型圖層調用-hitTest:會顯得更有意義,因為呈現圖層代表了用戶當前看到的圖層位置,而不是當前動畫結束之后的位置。

25.緩沖函數CAMediaTimingFunction
自定義緩沖函數

+ (instancetype)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;

- (instancetype)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
  • 那么該如何使用緩沖方程式呢?
    首先需要設置CAAnimation的timingFunction屬性,是CAMediaTimingFunction類的一個對象。如果想改變隱式動畫的計時函數,同樣也可以使用CATransaction+setAnimationTimingFunction:方法。

26.RunLoop

NSDefaultRunLoopMode - 標準優先級
NSRunLoopCommonModes- 高優先級
UITrackingRunLoopMode- 用于UIScrollView和別的控件的動畫

CADisplayLink : 屏幕更新執行一次刷新一次

self.timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step:)]; 
[self.timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 
[self.timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:UITrackingRunLoopMode];

NSTimer :標準的時間


self.timer = [NSTimer timerWithTimeInterval:1/60.0                                 target:self                               selector:@selector(step:)                               userInfo:nil                                repeats:YES];[[NSRunLoop mainRunLoop] addTimer:self.timer                          forMode:NSRunLoopCommonModes];

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容