Core Animation小記(一)

1. UIView 中沒(méi)有暴露出來(lái)的CALayer的功能:

陰影,圓角,帶顏色的邊框

3D變換

非矩形范圍

透明遮罩

多級(jí)非線(xiàn)性動(dòng)畫(huà)

CALayer 沒(méi)有,UIView有的功能:

對(duì)CALayer進(jìn)行了初步封裝,調(diào)用時(shí)較便捷

UIView可以使用自動(dòng)布局自適應(yīng)


2.使用CA需要引入庫(kù):QuartzCore到buildPhases中

3.contents屬性

你真正要賦值的類(lèi)型應(yīng)該是CGImageRef,它是一個(gè)指向CGImage結(jié)構(gòu)的指針

layer.contents = (__bridge id)image.CGImage

UIViewContentMode

typedef enum {

UIViewContentModeScaleToFill,

UIViewContentModeScaleAspectFit,??????// contents scaled to fit with fixed aspect. remainder is transparent

UIViewContentModeScaleAspectFill,???? // contents scaled to fill with fixed aspect. some portion of content may be clipped.

UIViewContentModeRedraw,??????????????// redraw on bounds change (calls -setNeedsDisplay)

UIViewContentModeCenter,??????????????// contents remain same size. positioned adjusted.

UIViewContentModeTop,

UIViewContentModeBottom,

UIViewContentModeLeft,

UIViewContentModeRight,

UIViewContentModeTopLeft,

UIViewContentModeTopRight,

UIViewContentModeBottomLeft,

UIViewContentModeBottomRight,

} UIViewContentMode;


CALayer與之對(duì)應(yīng)的為

UIViewContentModeScaleToFill -> (默認(rèn)效果)

UIViewContentModeScaleAspectFit -> kCAGravityResizeAspect

UIViewContentModeScaleAspectFill -> ?kCAGravityResizeAspectFill

4.UIView clipsToBounds ?maskToBounds

5.contentsRect

CALayer的contentsRect屬性允許我們?cè)趫D層邊框里顯示寄宿圖的一個(gè)子域

它使用了單位坐標(biāo)。在app中最有趣的地方在于一個(gè)叫做image sprites(圖片拼合)的

用法。圖片拼合后可以打包整合到一張大圖上一次性載入。相比多次載入不同的

圖片,這樣做能夠帶來(lái)很多方面的好處:內(nèi)存使用,載入時(shí)間,渲染性能等等。

6.contentsCenter

contentsCenter其實(shí)是一個(gè)CGRect,它定義了一個(gè)固定的邊框和一個(gè)在圖

層上可拉伸的區(qū)域。他工作起來(lái)的效果和UIImage里的-resizableImageWithCapInsets:方法效果非常類(lèi)似,只是它可以運(yùn)用

到任何寄宿圖,甚至包括在Core Graphics運(yùn)行時(shí)繪制的圖形

在XIB中可以使用Stretching

7.不同于UIView,當(dāng)圖層顯示在屏幕上時(shí),CALayer不會(huì)自動(dòng)重繪它的內(nèi)容。它把重繪的決定權(quán)交給了開(kāi)發(fā)者。

在UIView時(shí),當(dāng)使用寄宿了視圖的圖層的時(shí)候,你也不必實(shí)現(xiàn)-displayLayer:和-方法來(lái)繪制你的寄宿圖。通常做法是實(shí)現(xiàn)UIView的-方法,UIView就會(huì)幫你做完剩下的工作,包括在需要重繪的時(shí)候調(diào)用方法。

8.對(duì)于視圖或者圖層來(lái)說(shuō),并不是一個(gè)非常清晰的屬性,它其實(shí)是一個(gè)虛擬屬性,是根據(jù)bounds,和transform計(jì)算而來(lái),所以當(dāng)其中任何一個(gè)值發(fā)生改變,frame都會(huì)變化。相反,改變frame的值同樣會(huì)影響到他們當(dāng)中的值

視圖的center屬性和圖層的position屬性都指定了anchorPoint相對(duì)于父圖層的位置。圖層的anchorPoint通過(guò)position來(lái)控制它的frame位置,可以認(rèn)為anchorPoint是用來(lái)移動(dòng)圖層的把柄

anchorPoint是單位坐標(biāo),指position與width,height的比例,(0.1,0.1)指position位于左10.30方向,(0.5,0.5)位于中心,(0.5,0.9)位于6點(diǎn)種方向。

9.zPostion屬性在大多數(shù)情況下其實(shí)并不常用,可以用于在三維空間移動(dòng)和旋轉(zhuǎn)圖層做變換,此外, 最實(shí)用的功能就是改變圖層的顯示順序了。在zPostion,越大的越優(yōu)先顯示。不過(guò)其不能改變事件傳遞的順序

10.圓角

一般使用layer.cornerRadius和masksToBounds,對(duì)全部角設(shè)置為圓角并裁剪子視圖。

如果設(shè)置有些圓角有些直角,需要使用圖層蒙板或是CAShapeLayer

11.陰影往往可以達(dá)到圖層深度暗示的效果。也能夠用來(lái)強(qiáng)調(diào)正在顯示的圖層和優(yōu)先級(jí)。shadowOpacity是一個(gè)單位屬性,設(shè)置一個(gè)大于0對(duì)值,陰影就可以顯示在任何圖層之下。shadowOpacity是一個(gè)必須在0.0(不可見(jiàn))和1.0(完全不透明)之間的浮點(diǎn)數(shù)。想定制陰影,可以使用CAlayer的三個(gè)屬性:shadowColor,shadowOffset,shadowRadius

shadowColor是CGColorRef類(lèi)型

shadowOffset控制著陰影的方向和距離。它是一個(gè)CGSize值,寬度控制著陰影的橫向的位移,高度控制著縱向的位移。shadowOffset默認(rèn)是{0,-3},即隱形相對(duì)于Y軸有3個(gè)點(diǎn)點(diǎn)向上位移。

shadowRadius控制陰影的模糊度,當(dāng)它點(diǎn)值時(shí)0的時(shí)候,陰影就和視圖一樣有一個(gè)非常明確的邊界線(xiàn)。當(dāng)值越來(lái)越大的時(shí)候,邊界線(xiàn)看上去越來(lái)越模糊。

陰影繼承自?xún)?nèi)容的外形,會(huì)連區(qū)域外的子視圖的邊界一起做陰影。

陰影非常耗資源,尤其有多個(gè)子圖層,還有透明效果的寄宿圖的時(shí)候。如果知道隱形形狀時(shí)什么樣子,可以制定一個(gè)shadowPath來(lái)提高性能。其時(shí)一個(gè)CGPathRef類(lèi)型.

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView1;

@property (nonatomic, weak) IBOutlet UIView *layerView2;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//enable layer shadows

self.layerView1.layer.shadowOpacity = 0.5f;

self.layerView2.layer.shadowOpacity = 0.5f;

//create a square shadow

CGMutablePathRef squarePath = CGPathCreateMutable();

CGPathAddRect(squarePath, NULL, self.layerView1.bounds);

self.layerView1.layer.shadowPath = squarePath;

CGPathRelease(squarePath);

//create a circular shadow

CGMutablePathRef circlePath = CGPathCreateMutable();

CGPathAddEllipseInRect(circlePath, NULL, self.layerView2.bounds);

self.layerView2.layer.shadowPath = circlePath;

CGPathRelease(circlePath);

}

@end

但是如果是更加復(fù)雜一點(diǎn)的圖形,UIBezierPath類(lèi)會(huì)更合適

12.CALayer有一個(gè)屬性叫做mask.這個(gè)屬性本身就是個(gè)CALayer類(lèi)型,有和其他圖層一樣的繪制和布局屬性。它類(lèi)似于一個(gè)子圖層,相對(duì)于父圖層(即擁有該屬性的圖層)布局,但是它卻不是一個(gè)普通的子圖層。不同于那些繪制在父圖層中的子圖層,mask圖層定義了父圖層的部分可見(jiàn)區(qū)域。

mask屬性就像是一個(gè)餅干切割機(jī),mask圖層實(shí)心的部分會(huì)被保留下來(lái),其他的則會(huì)被拋棄。

如果mask圖層比父圖層要小,只有在mask圖層里面的內(nèi)容才是它關(guān)心的,除此以外的一切都會(huì)被隱藏起來(lái)。

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//create mask layer

CALayer *maskLayer = [CALayer layer];

maskLayer.frame = self.layerView.bounds;

UIImage *maskImage = [UIImage imageNamed:@"Cone.png"];

maskLayer.contents = (__bridge id)maskImage.CGImage;

//apply mask to image layer

self.imageView.layer.mask = maskLayer;

}

@end

CALayer蒙板圖層真正厲害的地方在于蒙板圖不局限于靜態(tài)圖。任何有圖層構(gòu)成的都可以作為mask屬性,這意味著你的蒙板可以通過(guò)代碼甚至是動(dòng)畫(huà)實(shí)時(shí)生成。

13.當(dāng)我們視圖顯示一個(gè)圖片的時(shí)候,都應(yīng)該正確地顯示這個(gè)圖片.原因如下:

能夠顯示最好的畫(huà)質(zhì),像素既沒(méi)有被壓縮也沒(méi)有被拉伸。

能更好的使用內(nèi)存,因?yàn)檫@就是所有你要存儲(chǔ)的東西。

最好的性能表現(xiàn),CPU不需要為此額外的計(jì)算。

14.UIView的transform是CGAffineTransform類(lèi)型,用于二維空間做旋轉(zhuǎn),縮放和平移

如下幾個(gè)函數(shù)都創(chuàng)建了一個(gè)CGAffineTransform實(shí)例:

CGAffineTransformMakeRotation(CGFloat angle) 旋轉(zhuǎn)

CGAffineTransformMakeScale(CGFloat sx, CGFloat sy) 縮放

CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty) 平移

UIView的transform對(duì)應(yīng)于CALayer的affineTransform

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView;

@end

@implementation ViewController

- (void)viewDidLoad

{

? ? ? ?[super viewDidLoad];

//rotate the layer 45 degrees

CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI_4);

self.layerView.layer.affineTransform = transform;

}

@end

Core Graphics提供了一系列的函數(shù)可以在一個(gè)變換的基礎(chǔ)上做更深層次的變換,如果做一個(gè)既要縮放又要旋轉(zhuǎn)的變換,這就會(huì)非常有用了。例如下面幾個(gè)函數(shù):

CGAffineTransformRotate(CGAffineTransform t,CGFloat angle)

CGAffineTransformScals(CGAffineTransform t, CGFloat sx, CGFloat sy)

CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)

當(dāng)操縱一個(gè)變換的時(shí)候,初始生成一個(gè)什么都不做的變換很重要--也就是創(chuàng)建一個(gè)CGAffineTransform類(lèi)型的空值,矩陣論中稱(chēng)作單位矩陣,Core Graphics同樣也提供了一個(gè)方便的常量:

CGAffineTransformIdentity

變換的順序會(huì)影響最終的結(jié)果,也就是說(shuō)旋轉(zhuǎn)之后的平移和平移之后的旋轉(zhuǎn)結(jié)果可能不同。

15.CALayer的transform是CATransform3D類(lèi)型,可以讓圖層在3D空間內(nèi)移動(dòng)或者旋轉(zhuǎn)

Core Animation提供了一系列的方法用來(lái)創(chuàng)建和組合CATransform3D類(lèi)型的矩陣,和Core Graphics的函數(shù)類(lèi)似,但是3D的平移和旋轉(zhuǎn)多出了一個(gè)z參數(shù),并且旋轉(zhuǎn)函數(shù)除了angle之外多出了x,y,z三個(gè)參數(shù),分別決定了每個(gè)坐標(biāo)軸方向上的旋轉(zhuǎn):

CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z)

CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz)

CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz)

CATransform3D的透視效果通過(guò)一個(gè)矩陣中一個(gè)很簡(jiǎn)單的元素來(lái)控制:m34。m34(圖5.9)用于按比例縮放X和Y的值來(lái)計(jì)算到底要離視角多遠(yuǎn)。m34的默認(rèn)值是0,我們可以通過(guò)設(shè)置m34為-1.0 /d來(lái)應(yīng)用透視效果,d代表了想象中視角相機(jī)和屏幕之間的距離,以像素為單位

CALayer有一個(gè)屬性叫做sublayerTransform。它也是CATransform3D類(lèi)型,但和對(duì)一個(gè)圖層的變換不同,它影響到所有的子圖層。這意味著你可以一次性對(duì)包含這些圖層的容器做變換,于是所有的子圖層都自動(dòng)繼承了這個(gè)變換方法。

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *containerView;

@property (nonatomic, weak) IBOutlet UIView *layerView1;

@property (nonatomic, weak) IBOutlet UIView *layerView2;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//apply perspective transform to container

CATransform3D perspective = CATransform3DIdentity;

perspective.m34 = - 1.0 / 500.0;

self.containerView.layer.sublayerTransform = perspective;

//rotate layerView1 by 45 degrees along the Y axis

CATransform3D transform1 = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);

self.layerView1.layer.transform = transform1;

//rotate layerView2 by 45 degrees along the Y axis

CATransform3D transform2 = CATransform3DMakeRotation(-M_PI_4, 0, 1, 0);

self.layerView2.layer.transform = transform2;

}

CALayer有一個(gè)叫做doubleSided的屬性來(lái)控制圖層的背面是否要被繪制。這是一個(gè)BOOL類(lèi)型,默認(rèn)為YES,如果設(shè)置為NO,那么當(dāng)圖層正面從相機(jī)視角消失的時(shí)候,它將不會(huì)被繪制。

盡管Core Animation圖層存在于3D空間之內(nèi),但它們并不都存在同一個(gè)3D空間。每個(gè)圖層的3D場(chǎng)景其實(shí)是扁平化的,當(dāng)你從正面觀察一個(gè)圖層,看到的實(shí)際上由子圖層創(chuàng)建的想象出來(lái)的3D場(chǎng)景,但當(dāng)你傾斜這個(gè)圖層,你會(huì)發(fā)現(xiàn)實(shí)際上這個(gè)3D場(chǎng)景僅僅是被繪制在圖層的表面。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Core Animation其實(shí)是一個(gè)令人誤解的命名。你可能認(rèn)為它只是用來(lái)做動(dòng)畫(huà)的,但實(shí)際上它是從一個(gè)叫做Laye...
    小貓仔閱讀 3,980評(píng)論 1 4
  • 書(shū)寫(xiě)的很好,翻譯的也棒!感謝譯者,感謝感謝! iOS-Core-Animation-Advanced-Techni...
    錢(qián)噓噓閱讀 2,444評(píng)論 0 6
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫(huà)效果,實(shí)現(xiàn)這些動(dòng)畫(huà)的過(guò)程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫(huà)全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,698評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫(huà)效果,實(shí)現(xiàn)這些動(dòng)畫(huà)的過(guò)程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫(huà)全貌。在這里你可以看...
    F麥子閱讀 5,273評(píng)論 5 13
  • 轉(zhuǎn)載:http://www.itdecent.cn/p/32fcadd12108 每個(gè)UIView有一個(gè)伙伴稱(chēng)為l...
    F麥子閱讀 6,595評(píng)論 0 13

友情鏈接更多精彩內(nèi)容