CALayer基礎(chǔ)

今天單純說(shuō)一下CALayer里面有的屬性和方法。反正宗旨就是隨意。
打開(kāi)CALayer定義文件:

@interface CALayer : NSObject <NSCoding, CAMediaTiming>
{
@private
  struct _CALayerIvars {
    int32_t refcount;
    uint32_t magic;
    void *layer;
#if TARGET_OS_MAC && !TARGET_RT_64_BIT
    void *unused1[8];
#endif
  } _attr;
}

/** Layer creation and initialization. **/

+ (instancetype)layer;

/* The designated initializer. */

- (instancetype)init;

- (instancetype)initWithLayer:(id)layer;

- (nullable id)presentationLayer;

- (id)modelLayer;

+ (nullable id)defaultValueForKey:(NSString *)key;

+ (BOOL)needsDisplayForKey:(NSString *)key;

- (BOOL)shouldArchiveValueForKey:(NSString *)key;

@property CGRect bounds;
...```

可以看到比較多的屬性和方法,挑一些方法和屬性來(lái)介紹一下。
***
先看看以下兩個(gè)方法:
  • (id)presentationLayer;
  • (id)modelLayer;```
    這兩個(gè)方法放在一起介紹,因?yàn)樗麄冎g是有關(guān)系。
    調(diào)用- (id)modelLayer返回的基本是當(dāng)前CALayer實(shí)例。其實(shí)這個(gè)就是你在代碼上修改的CALayer對(duì)象,比如像這樣:
CALayer *layer = [CALayer layer];
layer.position = CGPointMake(10, 10);
...```
這里你可能改了很多l(xiāng)ayer的其他屬性,無(wú)論改了多少,反正layer都幫你保存好了數(shù)據(jù)到堆里了。也就是說(shuō)修改的`layer.position = CGPointMake(10, 10)`存到了modelLayer上了。
調(diào)用`- (id)presentationLayer`同樣也會(huì)返回CALayer實(shí)例(注意當(dāng)被顯示出來(lái)之后再調(diào)用才不會(huì)nil),只不過(guò)這個(gè)實(shí)例不是你剛才在代碼上修改的那個(gè)layer了,而是屏幕上的layer的數(shù)據(jù),比如當(dāng)前屏幕上的`layer.position = CGPointMake(20, 20)`,這里從原來(lái)modelLayer的position{10, 10}變成了presentationLayer的position{20, 20}。
那么問(wèn)題來(lái)了:
+ 為什么會(huì)多一個(gè)presentationLayer出來(lái)呢?有什么作用呢?

先說(shuō)說(shuō)我們?cè)诖a上一般的做法。
比如我初始化了一個(gè)view出來(lái),大概是這樣的:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];```
那么把他加到父view上去后,這個(gè)view就會(huì)顯示在父view的{(0, 0), (100, 100)}的位置了。這個(gè)很好理解,因?yàn)槲乙潭ㄒ粋€(gè)view就必須指明他的坐標(biāo)位置和大小。現(xiàn)在我覺(jué)得這個(gè)view要向右過(guò)一點(diǎn)會(huì)看好一些,那么我們代碼大概是這么做的:

CGRect frame = view.frame;
frame.origin = CGPointMake(10, 0);
view.frame = frame;```
然后在屏幕上看到現(xiàn)在view比沒(méi)修改之前向右移動(dòng)了10,然后我覺(jué)得又要再向右過(guò)一點(diǎn)才好看,我重復(fù)之前的操作,大概是這么做的:

CGRect frame = view.frame;
frame.origin = CGPointMake(20, 0);
view.frame = frame;```
再然后我繼續(xù)任性,重復(fù)每次增加10,去修改x,一共重復(fù)5次。最終修改成這樣:

CGRect frame = view.frame;
frame.origin = CGPointMake(50, 0);
view.frame = frame;```
好了,現(xiàn)在后頭想,如果我修改的速度足夠快,每次看到屏幕上的view都向右移動(dòng)10,最終移動(dòng)到50的位置上,那么這個(gè)view看起來(lái)好像是在做動(dòng)畫一樣的移動(dòng)到50的位置上一樣。
如果不明白上面表達(dá)的意思的話,我想說(shuō)前面的字就用來(lái)充字?jǐn)?shù)的,其實(shí)簡(jiǎn)單的說(shuō)一句:`小時(shí)候,是否有試過(guò)在書上畫個(gè)小動(dòng)物,每一頁(yè)都畫得比前一頁(yè)稍微有那么一點(diǎn)的不同,畫得頁(yè)數(shù)足夠多之后,快速翻頁(yè),可以看到這個(gè)畫出來(lái)的小動(dòng)物在動(dòng)了`。在網(wǎng)上找了個(gè)效果[翻頁(yè)動(dòng)畫](http://tieba.baidu.com/p/1948629478)
相信讀者也明白是什么的一個(gè)效果了。現(xiàn)在來(lái)打個(gè)比喻,如果這本書只有一頁(yè)畫了這個(gè)小動(dòng)物,你能看出他動(dòng)嗎?顯然不可以。那么很多張稍微不一樣的就能看出動(dòng)了,那是因?yàn)槟切┊嬅嬖谌四X中留下的殘影(如果不明白這個(gè)的話,估計(jì)要問(wèn)問(wèn)學(xué)物理的還是化學(xué)的同學(xué)了吧)。
>屏幕上是怎么翻頁(yè),才能讓人類感動(dòng)畫的呢?可以閱讀[動(dòng)畫基礎(chǔ)](http://www.baidu.com)

對(duì)于程序也是一樣,你看到一個(gè)view在動(dòng),那是這個(gè)view位置在不斷的稍微變化,在你眼睛里留下的殘影。剛才說(shuō)了如果這本書只有一頁(yè)的話根本看不出動(dòng)畫來(lái),就好比如果只是設(shè)置了`frame.origin = CGPointMake(50, 0);`你就只會(huì)看到view被迅移到了x為50的位置上了。那個(gè)剛才是從10,20,30,40,50這樣的移動(dòng),只要足夠快,就可以看到動(dòng)起來(lái)了。
好了,關(guān)于
+ 為什么會(huì)多一個(gè)presentationLayer出來(lái)呢?有什么作用呢?

這個(gè)問(wèn)題回答完了,就是因?yàn)樵谧鰟?dòng)畫的時(shí)候,需要把過(guò)渡的位置顯示出來(lái),而不是迅移,人類眼睛留下了殘影才可以看到有動(dòng)畫。所以需要一個(gè)presentationLayer來(lái)存放這些過(guò)渡的數(shù)據(jù),然后再這些過(guò)渡數(shù)據(jù)一個(gè)個(gè)渲染出來(lái)(其實(shí)就是每一幀)。那么可以看出來(lái)presentationLayer是為做動(dòng)畫服務(wù)的(其實(shí)有沒(méi)為其他服務(wù)我就不知道了)。`所以假如在做動(dòng)畫的時(shí)候,presentationLayer里面的值就是當(dāng)前屏幕的值;而modelLayer的值就是動(dòng)畫結(jié)束后的值`。
>不知道是否會(huì)有讀者認(rèn)為老是說(shuō)一下CALayer又說(shuō)一下UIView?說(shuō)的都亂了?可以閱讀[CALayer和UIView的關(guān)系](http://www.lxweimin.com/p/6351116c2d19)

***
再看這個(gè)方法:
  • (BOOL)needsDisplayForKey:(NSString *)key;```

再看這些屬性:

@property CGRect bounds;
@property CGPoint position;
@property CGFloat zPosition;
@property CGPoint anchorPoint;
@property CGFloat anchorPointZ;
@property CGRect frame;```
關(guān)于這些屬性,其實(shí)官方文檔都說(shuō)得很清楚了,看以下這張圖吧:
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/1220247-5649867ee58b4c18.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
左邊的是iOS的,上圖展現(xiàn)了bounds,frame,position,anchorPoint,可以看到黃色矩形的左上角x和y在坐標(biāo)系上是{40, 60},但實(shí)際bounds的x和y是{0, 0},那么可以得出一個(gè)結(jié)論是`bounds的x和y跟坐標(biāo)系位置無(wú)關(guān)`;又可以看到實(shí)際上`frame的x和y才是跟才是坐標(biāo)系的位置,bounds的width,height和frame的width,height是一樣的`;anchorPoint點(diǎn)怎么理解呢?比較多的文章可能說(shuō)拿釘子釘一塊板到墻上的例子,不過(guò)我想說(shuō),旋轉(zhuǎn)木馬沒(méi)玩過(guò)也看過(guò)吧,就是一直圍繞著中心轉(zhuǎn)啊轉(zhuǎn)的木馬,anchorPoint就是這個(gè)選擇木馬圍繞中心旋轉(zhuǎn)的點(diǎn),其實(shí)就是`圓心的圓點(diǎn)(一個(gè)無(wú)限多邊形的圖形其實(shí)就是圓),所以圖上的anchorPoint是{0.5, 0.5}剛好在中間(因?yàn)閍nchorPoint的x和y最大值分別都是1)`;那么知道了anchorPoint,position就好理解了,position就是`圓點(diǎn)在坐標(biāo)系上的坐標(biāo)`。
需要注意一下的是:`layer的frame比較特別,他是通過(guò)position, bounds,anchorPoint和transform共同計(jì)算出來(lái)的`。什么意思呢?意思就是你`修改position, bounds,anchorPoint和transform的值都會(huì)改變到frame`。在做動(dòng)畫的時(shí)候就要注意了,改變position, bounds,anchorPoint和transform會(huì)導(dǎo)致frame的改變,可能就會(huì)出現(xiàn)你不想出現(xiàn)的情況,比如layer突然向上,下,左,右迅移了。
然后再來(lái)兩張圖:

![Paste_Image.png](http://upload-images.jianshu.io/upload_images/1220247-a90d1a00a3675bdc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/1220247-1a6f542347af6a08.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
第一張圖是一個(gè)UIView靜止的時(shí)候,第二張圖是UIView在做旋轉(zhuǎn)的時(shí)候,可以發(fā)現(xiàn)他們的frame不一樣了,明顯第二張圖變大了。這是因?yàn)檫@個(gè)UIView要保持矩形所以旋轉(zhuǎn)的時(shí)候就frame變大了。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,572評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過(guò)程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫全貌。在這里你可以看...
    F麥子閱讀 5,141評(píng)論 5 13
  • 轉(zhuǎn)載:http://www.lxweimin.com/p/18c306333080 1.UIView與CALayer...
    F麥子閱讀 559評(píng)論 0 1
  • 轉(zhuǎn)載:http://www.lxweimin.com/p/32fcadd12108 每個(gè)UIView有一個(gè)伙伴稱為l...
    F麥子閱讀 6,307評(píng)論 0 13
  • 在iOS實(shí)際開(kāi)發(fā)中常用的動(dòng)畫無(wú)非是以下四種:UIView動(dòng)畫,核心動(dòng)畫,幀動(dòng)畫,自定義轉(zhuǎn)場(chǎng)動(dòng)畫。 1.UIView...
    請(qǐng)叫我周小帥閱讀 3,159評(píng)論 1 23