專用圖層(上)
CALayer的孩子們
專用圖層是CALayer
的子類锋勺,各自具有不同的功能噪叙,使用之后能夠進(jìn)一步擴(kuò)展使用Core Animation繪圖的能力虑稼。
專用圖層的繪制通常是使用硬件加速完成的梦裂,通常會具有較好的性能腮介。且相較于使用UIView實(shí)現(xiàn)相應(yīng)效果,CALayer
會自帶隱式動畫斗埂,能有更為流暢的變化效果符糊。
目錄
CAShapeLayer - 矢量圖層
屬性
通過CGPath繪制圖形
CAGradientLayer - 漸變圖層
屬性
基礎(chǔ)漸變
多重漸變
基于漸變圖層的一些的特效
小結(jié)
CAShapeLayer - 矢量圖層
在上一節(jié)中凫海,我們已經(jīng)初步使用過CAShapeLayer
呛凶。CAShapeLayer
是一個通過矢量圖形而不是bitmap來繪制的圖層子類,可以指定顏色
線寬
等屬性行贪,用path
屬性定義需要繪制的圖形漾稀。相比較于通過使用Core Graphics
進(jìn)行繪制,他具有以下優(yōu)點(diǎn):
- 渲染快速建瘫。
CAShapeLayer
使用了硬件加速崭捍,繪制同一圖形會比用Core Graphics快很多。 - 高效使用內(nèi)存啰脚。一個
CAShapeLayer
不需要像普通CALayer
一樣創(chuàng)建一個寄宿圖形殷蛇,所以無論有多大实夹,都不會占用太多的內(nèi)存。 - 不會被圖層邊界剪裁掉粒梦。一個
CAShapeLayer
可以在邊界之外繪制亮航。 - 不會出現(xiàn)像素化。當(dāng)你給
CAShapeLayer
做3D變換時匀们,它不像一個有寄宿圖的普通圖層一樣變得像素化缴淋。
path
屬性是一個CGPathRef
類型對象,可以由(UIBezierPath *)path.CGPath
轉(zhuǎn)換獲得
屬性
-
@property(nullable) CGPathRef path;
:決定layer的形狀 -
@property(nullable) CGColorRef fillColor;
:決定layer的填充顏色泄朴,設(shè)置為[UIColor ClearColor]
時不進(jìn)行填充 -
@property(nullable) CGColorRef strokeColor;
:決定layer的線條顏色
以上是最常用的屬性
-
@property CGFloat strokeEnd;
:線條的結(jié)束位置(0~1重抖,對應(yīng)于path而言,默認(rèn)為1) -
@property CGFloat strokeStart;
:線條的起始位置(0~1祖灰,對應(yīng)于path而言钟沛,默認(rèn)為0)
strokeEnd
與strokeStart
屬性通常用于做動畫,比如你可以試一下[NSTimer scheduledTimerWithTimeInterval:0.01 repeats:YES block:^(NSTimer * _Nonnull timer) { shapeLayer.strokeStart += 0.005; }];
你會看到你的Path慢慢的就變短了夫植。
[寫到此處周老師忽然意識到進(jìn)度條可以用這個東西來寫]
-
@property(copy) NSString *lineCap;
:path端點(diǎn)樣式字符串常量讹剔,有3種樣式- ``kCALineCapButt`, // 無端點(diǎn)
- ``kCALineCapRound`, // 圓形端點(diǎn)
- ``kCALineCapSquare` // 方形端點(diǎn)
下圖從上到下依次為
kCALineCapButt
kCALineCapRound
kCALineCapSquare
樣式。
kCALineCapButt
樣式上和kCGLineCapButt
是一樣的详民,但是長度會長一丟丟1.2.png
-
@property(copy) NSString *lineJoin;
:拐角樣式字符串常量延欠,有3種樣式-
kCALineJoinMiter
, // 尖角 -
kCALineJoinRound
, // 圓角 -
kCALineJoinBevel
// 缺角
-
-
miterLimit
:最大斜接長度(只有在使用kCALineJoinMiter是才有效), 邊角的角度越小沈跨,斜接長度就會越大由捎,為了避免斜接長度過長,使用lineLimit屬性限制饿凛,如果斜接長度超過miterLimit狞玛,邊角就會以kCALineJoinBevel
類型來顯示
下圖從上到下依次為
kCALineJoinMiter
kCALineJoinRound
kCALineJoinBevel
樣式。此時miterLimit
的值足夠大涧窒,故會有一個很長很長的斜角心肪。1.3.png
-
@property(nullable, copy) NSArray<NSNumber *> *lineDashPattern;
:虛線數(shù)組(單位為pt) -
@property CGFloat lineDashPhase;
:虛線的偏移量(單位為pt)(可動畫屬性,修改后會觸發(fā)隱式動畫)
//設(shè)置虛線數(shù)組為[2,5,10],數(shù)組會按數(shù)組元素循環(huán)截斷線條(2pt為紅,5pt為透明,10pt為紅,2pt為白.....) shapeLayer.lineDashPattern = @[@2, @5, @10]; //lineDashPhase的動畫屬性纠吴,能夠事實(shí)更改并生效 [NSTimer scheduledTimerWithTimeInterval:0.02 repeats:YES block:^(NSTimer * _Nonnull timer) { shapeLayer.lineDashPhase += 1; }];
1.4.gif
通過CGPath繪制圖形
CAShapeLayer
能夠繪制所有可以通過CGPath
來表示的形狀硬鞍,不論閉合與否,且可以在一個圖層上繪制多個不同的形狀戴已。其次可以控制一些屬性比如lineWith
(線寬固该,用點(diǎn)表示單位),lineCap
(線條結(jié)尾的樣子)糖儡,和lineJoin
(線條之間的結(jié)合點(diǎn)的樣子)伐坏;但是在一個圖層中,所有這些屬性只能有一個樣式握联,所以你如果想用不同的顏色/粗細(xì)/風(fēng)格來繪制多個形狀桦沉,那就需要使用多個圖層每瞒。
接下來是用CAShapeLayer
繪制一個火柴人的例子:
UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:CGPointMake(175, 100)];
//下面是畫圖的代碼
[path addArcWithCenter:CGPointMake(150, 100) radius:25 startAngle:0 endAngle:2*M_PI clockwise:YES];
[path moveToPoint:CGPointMake(150, 125)];
[path addLineToPoint:CGPointMake(150, 175)];
[path addLineToPoint:CGPointMake(125, 225)];
[path moveToPoint:CGPointMake(150, 175)];
[path addLineToPoint:CGPointMake(175, 225)];
[path moveToPoint:CGPointMake(100, 150)];
[path addLineToPoint:CGPointMake(200, 150)];
//創(chuàng)建shapeLayer,配置屬性
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.strokeColor = [UIColor redColor].CGColor;//線條顏色為紅色
shapeLayer.fillColor = [UIColor clearColor].CGColor;//填充顏色為透明纯露,否則會對線條包圍的部分進(jìn)行填充
shapeLayer.lineWidth = 5;
shapeLayer.lineJoin = kCALineJoinRound;//圓形折角
shapeLayer.lineCap = kCALineCapRound;//圓形斷點(diǎn)
shapeLayer.path = path.CGPath;
//添加至superLayer后生效
[self.view.layer addSublayer:shapeLayer];
CAGradientLayer - 漸變圖層
CAGradientLayer
是用來生成兩種或更多顏色平滑漸變的独泞,繪制使用了硬件加速,同時也可以用Core Graphics
復(fù)制一個CAGradientLayer
并將內(nèi)容繪制到一個普通圖層的寄宿圖苔埋。
屬性
-
@property(nullable, copy) NSArray *colors
:漸變的顏色數(shù)組懦砂,數(shù)組成員接受CGColorRef
,非NSObject對象组橄,所以需要bridge
轉(zhuǎn)換荞膘。默認(rèn)選擇均勻分布 -
@property(nullable, copy) NSArray<NSNumber *> *locations
:漸變顏色數(shù)組對應(yīng)的點(diǎn)坐標(biāo),延漸變軸線分布的0~1之間的浮點(diǎn)數(shù)玉工∮鹱剩可選屬性,若賦值則必須與colors
數(shù)量一致 -
@property CGPoint startPoint
:漸變的起始點(diǎn)遵班,點(diǎn)坐標(biāo) -
@property CGPoint endPoint
:漸變的終點(diǎn)屠升,點(diǎn)坐標(biāo),漸變以起點(diǎn)與終點(diǎn)連線作為漸變軸進(jìn)行漸變
例:設(shè)置
startPoint
為{0, 0.5}狭郑,endPoint
為{1, 0.5}腹暖,漸變軸的方向2.1.jpg
-
@property(copy) NSString *type
:漸變繪制樣式,目前只有一種-
kCAGradientLayerAxial
:軸向漸變
-
基礎(chǔ)漸變
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = CGRectMake(100, 100, 200, 200);
[self.view.layer addSublayer:gradientLayer];
//設(shè)置漸變顏色為[紅, 藍(lán)]
gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor, (__bridge id)[UIColor blueColor].CGColor];
//設(shè)置起點(diǎn)為左上角翰萨,重點(diǎn)為右下角
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(1, 1);
多重漸變
colors
屬性可以包含很多顏色脏答,locations
屬性定義了這些顏色的位置(沿軸線分布的距離)。
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = CGRectMake(100, 100, 200, 200);
[self.view.layer addSublayer:gradientLayer];
gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor,
(__bridge id) [UIColor yellowColor].CGColor,
(__bridge id)[UIColor greenColor].CGColor];
gradientLayer.locations = @[@0.0, @0.25, @0.5];
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(1, 1);
一些騷騷的特效
雖然漸變圖層看起來土土的還很鄉(xiāng)非亩鬼,但是配合其他繪制機(jī)制殖告,可以組合變化出一些很酷炫的操作。
比如配合蒙板可以實(shí)現(xiàn):
這個效果的原理是:漸變圖層做漸變動畫雳锋,使用一個UILabel.layer
作為蒙板黄绩,達(dá)到文字發(fā)生漸變的效果。
- 首先我們需要創(chuàng)建一個黑白相間的漸變圖層玷过,并為其添加動畫效果
- 然后再創(chuàng)建一個UILabel爽丹,取它的layer作為gradientLayer的蒙板
//創(chuàng)建漸變圖層
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
[self.view.layer addSublayer:gradientLayer];
gradientLayer.frame = CGRectMake(0, 200, kScreenWidth, 64);
//設(shè)置漸變軸為從左往右
gradientLayer.startPoint = CGPointMake(0, 0.5);
gradientLayer.endPoint = CGPointMake(1, 0.5);
//黑白相間的顏色
gradientLayer.colors = @[
(__bridge id)[UIColor blackColor].CGColor,
(__bridge id)[UIColor whiteColor].CGColor,
(__bridge id)[UIColor blackColor].CGColor,];
//因?yàn)橐鰟赢嫞詌ocations屬性可以是任何NSArray對象就可以了
//甚至你可以這樣寫: .locations = @[@"干死黃旭東", @"蟑螂加兩攻"];
//下面是規(guī)范寫法
gradientLayer.locations = @[@0.25,@0.5,@0.75];
//添加動畫
//動畫KeyPath指定為"locations"冶匹,表示要對gradientLayer.locations屬性做動畫
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"locations"];
basicAnimation.fromValue = @[@0, @0, @0.25];
basicAnimation.toValue = @[@0.75, @1, @1];
basicAnimation.duration = 2.5;
basicAnimation.repeatCount = HUGE;
[gradientLayer addAnimation:basicAnimation forKey:nil];
//接下來創(chuàng)建作為蒙板的Label
//注意這個frame习劫,是相對gradientLayer的坐標(biāo)
UILabel *label = [[UILabel alloc] initWithFrame:gradientLayer.bounds];
label.text = @"滑動狗頭解鎖 >>";
label.alpha = 0.5;
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:30];
//一定要強(qiáng)引用這個Label避免被釋放
self.label = label;
//重點(diǎn):設(shè)置Label的layer為gradientLayer的蒙板咆瘟,不需要做addSubView操作
gradientLayer.mask = label.layer;
小結(jié)
CAShapeLayer
與CAGradientLayer
都是具有繪制作用的專用圖層嚼隘,而且他們的繪制都是使用硬件加速完成的,他們通常能夠以相對較高的性能完成一些簡單的繪制和顯示效果工作袒餐。例如在日常工作中遇到需要做簡單填充效果的時候飞蛹,可以使用專用圖層來替代Core Graphics
提升性能谤狡,而且由于CALayer帶有隱式動畫,還可以省去動畫調(diào)度代碼的編寫卧檐。