周老師的QuartzCore教程 - 專用圖層(上)

專用圖層(上)

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)

strokeEndstrokeStart屬性通常用于做動畫,比如你可以試一下

[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];
1.1.png

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);
2.2.png

多重漸變

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);
2.3.png

一些騷騷的特效

雖然漸變圖層看起來土土的還很鄉(xiāng)非亩鬼,但是配合其他繪制機(jī)制殖告,可以組合變化出一些很酷炫的操作。

比如配合蒙板可以實(shí)現(xiàn):

2.4.gif

這個效果的原理是:漸變圖層做漸變動畫雳锋,使用一個UILabel.layer作為蒙板黄绩,達(dá)到文字發(fā)生漸變的效果。

  • 首先我們需要創(chuàng)建一個黑白相間的漸變圖層玷过,并為其添加動畫效果
2.5.gif
  • 然后再創(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é)

CAShapeLayerCAGradientLayer都是具有繪制作用的專用圖層嚼隘,而且他們的繪制都是使用硬件加速完成的,他們通常能夠以相對較高的性能完成一些簡單的繪制和顯示效果工作袒餐。例如在日常工作中遇到需要做簡單填充效果的時候飞蛹,可以使用專用圖層來替代Core Graphics提升性能谤狡,而且由于CALayer帶有隱式動畫,還可以省去動畫調(diào)度代碼的編寫卧檐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末墓懂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子霉囚,更是在濱河造成了極大的恐慌捕仔,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盈罐,死亡現(xiàn)場離奇詭異榜跌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)盅粪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進(jìn)店門钓葫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人票顾,你說我怎么就攤上這事础浮。” “怎么了奠骄?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵豆同,是天一觀的道長。 經(jīng)常有香客問我含鳞,道長诱告,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任民晒,我火速辦了婚禮精居,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘潜必。我一直安慰自己靴姿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布磁滚。 她就那樣靜靜地躺著铺韧,像睡著了一般趁矾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天立倍,我揣著相機(jī)與錄音,去河邊找鬼悉罕。 笑死笼平,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的陨仅。 我是一名探鬼主播津滞,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼铝侵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了触徐?” 一聲冷哼從身側(cè)響起咪鲜,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎撞鹉,沒想到半個月后疟丙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸟雏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年隆敢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片崔慧。...
    茶點(diǎn)故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡拂蝎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出惶室,到底是詐尸還是另有隱情温自,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布皇钞,位于F島的核電站悼泌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏夹界。R本人自食惡果不足惜馆里,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望可柿。 院中可真熱鬧鸠踪,春花似錦、人聲如沸复斥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽目锭。三九已至评汰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痢虹,已是汗流浹背被去。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留奖唯,地道東北人惨缆。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親踪央。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評論 2 361

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