《Core Animation》-- CALayer基礎(chǔ)屬性及方法介紹

如圖:UIView可以處理觸摸事件议街,但CALayer是不支持交互的(不清楚具體的相應(yīng)鏈的)秃踩。實(shí)際上這些背后關(guān)聯(lián)的圖層才是真正用來在屏幕上顯示和做動畫嘁扼,UIView僅僅是對它的一個(gè)封裝拷肌,提供了一些iOS類似于處理觸摸的具體功能糟秘,以及Core Animation底層方法的高級接口简逮。

<四個(gè)層級關(guān)系>:視圖層級、圖層樹尿赚、呈現(xiàn)樹和渲染樹散庶。

屬性介紹

  • Contents:

事實(shí)上,你真正要賦值的類型應(yīng)該是CGImageRef凌净,它是一個(gè)指向CGImage結(jié)構(gòu)的指針悲龟。UIImage有一個(gè)CGImage屬性,它返回一個(gè)"CGImageRef",如果你想把這個(gè)值直接賦值給CALayer的contents冰寻,那你將會得到一個(gè)編譯錯誤须教。因?yàn)镃GImageRef并不是一個(gè)真正的Cocoa對象,而是一個(gè)Core Foundation類型性雄∶恍叮可以通過bridged關(guān)鍵字轉(zhuǎn)換。

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

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

//對應(yīng)UIView的center.
@property CGPoint position;
  • anchorPoint:

錨點(diǎn)煤蚌,可以理解為固定圖層的點(diǎn)。相對于自身坐標(biāo)系细卧,取值范圍0~1尉桩,默認(rèn)(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:

屬性定義了寄宿圖的像素尺寸和視圖大小的比例止邮,默認(rèn)情況下它是一個(gè)值為1.0的浮點(diǎn)數(shù)这橙。當(dāng)設(shè)置了contentsGravity屬性會有所影響奏窑。

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

屬性允許我們在圖層邊框里顯示寄宿圖的一個(gè)子域鹰晨,contentsRect不是按點(diǎn)來計(jì)算的墨叛,它使用了單位坐標(biāo),單位坐標(biāo)指定在0到1之間模蜡,是一個(gè)相對值(像素和點(diǎn)就是絕對值)

@property CGRect contentsRect;

其實(shí)是一個(gè)CGRect漠趁,它定義了一個(gè)固定的邊框和一個(gè)在圖層上可拉伸的區(qū)域。

//單位坐標(biāo)哩牍,定義的區(qū)域會被全面拉伸(也就是從四個(gè)方向進(jìn)行放大或者縮小)棚潦,所'侵占'的地方的視圖也會進(jìn)行相應(yīng)的拉伸變換。
@property CGRect contentsCenter;
  • masksToBounds:
//等同于UIView的clipsToBounds.
@property BOOL masksToBounds;
  • mask:

是個(gè)CALayer類型膝昆,有和其他圖層一樣的繪制和布局屬性。它類似于一個(gè)子圖層叠必,相對于父圖層(即擁有該屬性的圖層)布局荚孵,但是它卻不是一個(gè)普通的子圖層。不同于那些繪制在父圖層中的子圖層纬朝,mask圖層定義了父圖層的部分可見區(qū)域收叶。

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

--值的介紹:

1共苛。kCAFilterLinear:默認(rèn)值判没,采用雙線性濾波算法,它在大多數(shù)情況下都表現(xiàn)良好隅茎。雙線性濾波算法通過對多個(gè)像素取樣最終生成新的值澄峰,得到一個(gè)平滑的表現(xiàn)不錯的拉伸。但是當(dāng)放大倍數(shù)比較大的時(shí)候圖片就模糊不清了辟犀。

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

3出嘹。kCAFilterNearest:取樣最近的單像素點(diǎn)而不管其他的顏色席楚。這樣做非常快税稼,也不會使圖片模糊烦秩。但是垮斯,最明顯的效果就是,會使得壓縮圖片更糟闻镶,圖片放大之后也顯得塊狀或是馬賽克嚴(yán)重甚脉。(不推薦)。

--總結(jié):

對于比較小的圖或者是差異特別明顯铆农,極少斜線的大圖牺氨,最近過濾算法會保留這種差異明顯的特質(zhì)以呈現(xiàn)更好的結(jié)果。但是對于大多數(shù)的圖尤其是有很多斜線或是曲線輪廓的圖片來說墩剖,最近過濾算法會導(dǎo)致更差的結(jié)果猴凹。換句話說,線性過濾保留了形狀岭皂,最近過濾則保留了像素的差異郊霎。

  • shouldRasterize:

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

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

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

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

—栗子:

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

代理

CALayer有一個(gè)可選的delegate屬性骡苞,實(shí)現(xiàn)了CALayerDelegate協(xié)議,當(dāng)CALayer需要一個(gè)內(nèi)容特定的信息時(shí)楷扬,就會從協(xié)議中請求解幽。CALayerDelegate是一個(gè)非正式協(xié)議,其實(shí)就是說沒有CALayerDelegate @protocol可以讓你在類里面引用啦烘苹。你只需要調(diào)用你想調(diào)用的方法躲株,CALayer會幫你做剩下的。(delegate屬性被聲明為id類型螟加,所有的代理方法都是可選的)徘溢。

  • 當(dāng)需要被重繪時(shí),CALayer會請求它的代理給他一個(gè)寄宿圖來顯示捆探。它通過調(diào)用下面這個(gè)方法做到的:
- (void)displayLayer:(CALayerCALayer *)layer;
  • 如果代理不實(shí)現(xiàn)-displayLayer:方法然爆,CALayer就會轉(zhuǎn)而嘗試調(diào)用下面這個(gè)方法,在調(diào)用這個(gè)方法之前黍图,CALayer創(chuàng)建了一個(gè)合適尺寸的空寄宿圖(尺寸由boundscontentsScale決定)和一個(gè)Core Graphics的繪制上下文環(huán)境曾雕,為繪制寄宿圖做準(zhǔn)備,他作為ctx參數(shù)傳入助被。
- (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協(xié)議剖张。

    [delegateLayer display];//這里需要顯式地調(diào)用了-display切诀。不同于UIView,當(dāng)圖層顯示在屏幕上時(shí)搔弄,CALayer不會自動重繪它的內(nèi)容幅虑。它把重繪的決定權(quán)交給了開發(fā)者。
- (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屬性顾犹,繪制的那個(gè)圓仍然沿邊界被裁剪了倒庵。這是因?yàn)楫?dāng)你使用CALayerDelegate繪制寄宿圖的時(shí)候,并沒有對超出邊界外的內(nèi)容提供繪制支持炫刷。

當(dāng)UIView創(chuàng)建了它的宿主圖層時(shí)擎宝,它就會自動地把圖層的delegate設(shè)置為它自己,并提供了一個(gè)-displayLayer:的實(shí)現(xiàn)浑玛,那所有的問題就都沒了绍申。

當(dāng)使用寄宿了視圖的圖層的時(shí)候,你也不必實(shí)現(xiàn)-displayLayer:-drawLayer:inContext:方法來繪制你的寄宿圖顾彰。通常做法是實(shí)現(xiàn)UIView的-drawRect:方法极阅,UIView就會幫你做完剩下的工作,包括在需要重繪的時(shí)候調(diào)用-display方法涨享。

其它方法

  • UIView會在初始化的時(shí)候調(diào)用+layerClass方法涂屁,然后用它的返回類型來創(chuàng)建宿主圖層。(特別適用灰伟,返回的值代表self.layer)
+(Class)layerClass
  • 以下方法可以把定義在一個(gè)圖層坐標(biāo)系下的點(diǎn)或者矩形轉(zhuǎn)換成另一個(gè)圖層坐標(biāo)系下的點(diǎn)或者矩形.
- (CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer;//得到layer上的point的點(diǎn)相對于方法調(diào)用者的相對point。
- (CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer;
- (CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer;
- (CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;
  • 接受一個(gè)在本圖層坐標(biāo)系下的CGPoint儒旬,如果這個(gè)點(diǎn)在圖層frame范圍內(nèi)就返回YES栏账。需要把觸摸坐標(biāo)轉(zhuǎn)換成每個(gè)圖層坐標(biāo)系下的坐標(biāo),結(jié)果很不方便栈源。
- (BOOL)containsPoint:(CGPoint)p;
  • 方法同樣接受一個(gè)CGPoint類型參數(shù)挡爵,而不是BOOL類型,它返回圖層本身甚垦,或者包含這個(gè)坐標(biāo)點(diǎn)的葉子節(jié)點(diǎn)圖層茶鹃。這意味著不再需要像使用-containsPoint:那樣,人工地在每個(gè)子圖層變換或者測試點(diǎn)擊的坐標(biāo)艰亮。如果這個(gè)點(diǎn)在最外面圖層的范圍之外闭翩,則返回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) {

    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迄埃,一起剝皮案震驚了整個(gè)濱河市疗韵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侄非,老刑警劉巖蕉汪,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件流译,死亡現(xiàn)場離奇詭異,居然都是意外死亡者疤,警方通過查閱死者的電腦和手機(jī)福澡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來驹马,“玉大人革砸,你說我怎么就攤上這事】妫” “怎么了业岁?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長寇蚊。 經(jīng)常有香客問我笔时,道長,這世上最難降的妖魔是什么仗岸? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任允耿,我火速辦了婚禮,結(jié)果婚禮上扒怖,老公的妹妹穿的比我還像新娘较锡。我一直安慰自己,他們只是感情好盗痒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布蚂蕴。 她就那樣靜靜地躺著,像睡著了一般俯邓。 火紅的嫁衣襯著肌膚如雪骡楼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天稽鞭,我揣著相機(jī)與錄音鸟整,去河邊找鬼。 笑死朦蕴,一個(gè)胖子當(dāng)著我的面吹牛篮条,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吩抓,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼涉茧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了琴拧?” 一聲冷哼從身側(cè)響起降瞳,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后挣饥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體除师,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年扔枫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了汛聚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡短荐,死狀恐怖倚舀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情忍宋,我是刑警寧澤痕貌,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站糠排,受9級特大地震影響舵稠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜入宦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一哺徊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧乾闰,春花似錦落追、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至病苗,卻和暖如春谣膳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背铅乡。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留烈菌,地道東北人阵幸。 一個(gè)月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像芽世,于是被迫代替她去往敵國和親挚赊。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評論 2 355

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