《Core Animation》-- CALayer基礎屬性及方法介紹

如圖:UIView可以處理觸摸事件,但CALayer是不支持交互的(不清楚具體的相應鏈的)。實際上這些背后關聯的圖層才是真正用來在屏幕上顯示和做動畫,UIView僅僅是對它的一個封裝,提供了一些iOS類似于處理觸摸的具體功能,以及Core Animation底層方法的高級接口。

<四個層級關系>:視圖層級、圖層樹、呈現樹和渲染樹。

屬性介紹

  • Contents:

事實上,你真正要賦值的類型應該是CGImageRef,它是一個指向CGImage結構的指針。UIImage有一個CGImage屬性,它返回一個"CGImageRef",如果你想把這個值直接賦值給CALayer的contents,那你將會得到一個編譯錯誤。因為CGImageRef并不是一個真正的Cocoa對象,而是一個Core Foundation類型??梢酝ㄟ^bridged關鍵字轉換。

@property(nullable, strong) id contents;
  • contentMode:
//對應UIView的contentMode.  
@property(copy) NSString *contentsGravity;
  • geometryFlipped:
//決定了一個圖層的坐標是否相對于父圖層垂直翻轉。是為了適配iOS和OS X兩種不同坐標系的情況。
@property(getter=isGeometryFlipped) BOOL geometryFlipped;
  • zPosition:
//常用于做CATransform3D變換及更改圖層的顯示順序。<不能改變事件傳遞的順序>
@property CGFloat zPosition;
  • anchorPointZ:
//在Z軸上描述圖層位置的浮點類型
@property CGFloat anchorPointZ;
  • position:

指定了anchorPoint相對于父圖層的位置。

//對應UIView的center.
@property CGPoint position;
  • anchorPoint:

錨點,可以理解為固定圖層的點。相對于自身坐標系,取值范圍0~1,默認(0.5,0.5)。

@property CGPoint anchorPoint;

position和anchorPoint的換算公式:徹底理解position和anchorPoint

position.x = frame.origin.x + anchorPoint.x * bounds.size.width;  
position.y = frame.origin.y + anchorPoint.y * bounds.size.height;
  • contentsScale:

屬性定義了寄宿圖的像素尺寸和視圖大小的比例,默認情況下它是一個值為1.0的浮點數。當設置了contentsGravity屬性會有所影響。

//如果contentsScale設置為1.0,將會以每個點1個像素繪制圖片。并且把contentsGravity設置為kCAGravityCenter(這個值并不會拉伸圖片),那將會有很明顯的變化。
@property CGFloat contentsScale
  • contentsRect:

屬性允許我們在圖層邊框里顯示寄宿圖的一個子域,contentsRect不是按點來計算的,它使用了單位坐標,單位坐標指定在0到1之間,是一個相對值(像素和點就是絕對值)

@property CGRect contentsRect;

其實是一個CGRect,它定義了一個固定的邊框和一個在圖層上可拉伸的區域。

//單位坐標,定義的區域會被全面拉伸(也就是從四個方向進行放大或者縮小),所'侵占'的地方的視圖也會進行相應的拉伸變換。
@property CGRect contentsCenter;
  • masksToBounds:
//等同于UIView的clipsToBounds.
@property BOOL masksToBounds;
  • mask:

是個CALayer類型,有和其他圖層一樣的繪制和布局屬性。它類似于一個子圖層,相對于父圖層(即擁有該屬性的圖層)布局,但是它卻不是一個普通的子圖層。不同于那些繪制在父圖層中的子圖層,mask圖層定義了父圖層的部分可見區域。

@property(nullable, strong) CALayer *mask;
  • minificationFilter && magnificationFilter
@property(copy) NSString *minificationFilter;//縮?。?@property(copy) NSString *magnificationFilter;//放大:

--值的介紹:

1。kCAFilterLinear:默認值,采用雙線性濾波算法,它在大多數情況下都表現良好。雙線性濾波算法通過對多個像素取樣最終生成新的值,得到一個平滑的表現不錯的拉伸。但是當放大倍數比較大的時候圖片就模糊不清了。

2。kCAFilterTrilinear:三線性濾波算法存儲了多個大小情況下的圖片(也叫多重貼圖),并三維取樣,同時結合大圖和小圖的存儲進而得到最后的結果。這不僅提高了性能,也避免了小概率因舍入錯誤引起的取樣失靈的問題.

3。kCAFilterNearest:取樣最近的單像素點而不管其他的顏色。這樣做非常快,也不會使圖片模糊。但是,最明顯的效果就是,會使得壓縮圖片更糟,圖片放大之后也顯得塊狀或是馬賽克嚴重。(不推薦)。

--總結:

對于比較小的圖或者是差異特別明顯,極少斜線的大圖,最近過濾算法會保留這種差異明顯的特質以呈現更好的結果。但是對于大多數的圖尤其是有很多斜線或是曲線輪廓的圖片來說,最近過濾算法會導致更差的結果。換句話說,線性過濾保留了形狀,最近過濾則保留了像素的差異。

  • shouldRasterize:

為了啟用shouldRasterize屬性,我們設置了圖層的rasterizationScale屬性。默認情況下,所有圖層拉伸都是1.0, 所以如果你使用了shouldRasterize屬性,你就要確保你設置了rasterizationScale屬性去匹配屏幕,以防止出現Retina屏幕像素化的問題。(info.plist文件中有個全局設置屬性:UIViewGroupOpacity)

//組透明效果
@property BOOL shouldRasterize;
  • affineTransform

這里只提供了set和get方法。

- (CGAffineTransform)affineTransform;
- (void)setAffineTransform:(CGAffineTransform)m;

—栗子:

CGAffineTransform  affine = CGAffineTransformMakeRotation(M_PI_4);
blueLayer.affineTransform = affine;

代理

CALayer有一個可選的delegate屬性,實現了CALayerDelegate協議,當CALayer需要一個內容特定的信息時,就會從協議中請求。CALayerDelegate是一個非正式協議,其實就是說沒有CALayerDelegate @protocol可以讓你在類里面引用啦。你只需要調用你想調用的方法,CALayer會幫你做剩下的。(delegate屬性被聲明為id類型,所有的代理方法都是可選的)。

  • 當需要被重繪時,CALayer會請求它的代理給他一個寄宿圖來顯示。它通過調用下面這個方法做到的:
- (void)displayLayer:(CALayerCALayer *)layer;
  • 如果代理不實現-displayLayer:方法,CALayer就會轉而嘗試調用下面這個方法,在調用這個方法之前,CALayer創建了一個合適尺寸的空寄宿圖(尺寸由boundscontentsScale決定)和一個Core Graphics的繪制上下文環境,為繪制寄宿圖做準備,他作為ctx參數傳入。
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;

—栗子:

    CALayer * delegateLayer = [CALayer layer];
    [self.view.layer addSublayer:delegateLayer];
    delegateLayer.frame = CGRectMake(50, 100, 300, 400);
    delegateLayer.backgroundColor = [UIColor brownColor].CGColor;
    delegateLayer.delegate = self;//這里需遵循CALayerDelegate協議。

    [delegateLayer display];//這里需要顯式地調用了-display。不同于UIView,當圖層顯示在屏幕上時,CALayer不會自動重繪它的內容。它把重繪的決定權交給了開發者。
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
  //draw a thick red circle
  CGContextSetLineWidth(ctx, 10.0f);
  CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
  CGContextStrokeEllipseInRect(ctx, layer.bounds);
}

—效果:

95187B0D-764B-46CA-B26E-C4E835BD8D03.jpeg

—注意:

盡管我們沒有用masksToBounds屬性,繪制的那個圓仍然沿邊界被裁剪了。這是因為當你使用CALayerDelegate繪制寄宿圖的時候,并沒有對超出邊界外的內容提供繪制支持。

當UIView創建了它的宿主圖層時,它就會自動地把圖層的delegate設置為它自己,并提供了一個-displayLayer:的實現,那所有的問題就都沒了。

當使用寄宿了視圖的圖層的時候,你也不必實現-displayLayer:-drawLayer:inContext:方法來繪制你的寄宿圖。通常做法是實現UIView的-drawRect:方法,UIView就會幫你做完剩下的工作,包括在需要重繪的時候調用-display方法。

其它方法

  • UIView會在初始化的時候調用+layerClass方法,然后用它的返回類型來創建宿主圖層。(特別適用,返回的值代表self.layer)
+(Class)layerClass
  • 以下方法可以把定義在一個圖層坐標系下的點或者矩形轉換成另一個圖層坐標系下的點或者矩形.
- (CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer;//得到layer上的point的點相對于方法調用者的相對point。
- (CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer;
- (CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer;
- (CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;
  • 接受一個在本圖層坐標系下的CGPoint,如果這個點在圖層frame范圍內就返回YES。需要把觸摸坐標轉換成每個圖層坐標系下的坐標,結果很不方便。
- (BOOL)containsPoint:(CGPoint)p;
  • 方法同樣接受一個CGPoint類型參數,而不是BOOL類型,它返回圖層本身,或者包含這個坐標點的葉子節點圖層。這意味著不再需要像使用-containsPoint:那樣,人工地在每個子圖層變換或者測試點擊的坐標。如果這個點在最外面圖層的范圍之外,則返回nil。
- (nullable CALayer *)hitTest:(CGPoint)p;

—栗子:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGPoint point = [[touches anyObject] locationInView:self.view];
    CALayer *layer = [self.layerView.layer hitTest:point];
    if (layer == self.blueLayer) {

    } else if (layer == self.layerView.layer) {

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

推薦閱讀更多精彩內容