CAShapeLayer
繼承自CALayer
,所以,可以使用CALayer
的全部屬性。可是,CAShapeLayer
須要和貝塞爾曲線配合使用纔有意義。git
關於UIBezierPath
,請閱讀文章iOS UIBezierPth精講github
看看官方說明:框架
1性能 2學習 3測試 4動畫 5ui 6spa 7code 8 9 |
/* The shape layer draws a cubic Bezier spline in its coordinate space. * * The spline is described using a CGPath object and may have both fill * and stroke components (in which case the stroke is composited over * the fill). The shape as a whole is composited between the layer's * contents and its first sublayer. */
|
上面只是部分說明內容,因爲較長,只放一部分出來。這裏是說CAShapeLayer
是在其座標系統內繪製貝塞爾曲線的。所以,使用CAShapeLayer
須要與UIBezierPath
一塊兒使用。
它有一個path
屬性,而UIBezierPath
就是對CGPathRef
類型的封裝,所以這二者配合起來使用才能夠的哦!
1 2 3 |
@property(nullable) CGPathRef path;
|
drawRect
:屬於CoreGraphics
框架,佔用CPU
,性能消耗大
CAShapeLayer
:屬於CoreAnimation
框架,經過GPU
來渲染圖形,節省性能。動畫渲染直接提交給手機GPU
,不消耗內存
這二者各有各的用途,而不是說有了CAShapeLayer
就不須要drawRect
。
舒適提示:
drawRect
只是一個方法而已,是UIView
的方法,重寫此方法能夠完成咱們的繪製圖形功能。
CAShapeLayer
與UIBezierPath
的關係:
CAShapeLayer
中shape
表明形狀的意思,因此須要形狀才能生效
貝塞爾曲線能夠建立基於矢量的路徑,而UIBezierPath
類是對CGPathRef
的封裝
貝塞爾曲線給CAShapeLayer
提供路徑,CAShapeLayer
在提供的路徑中進行渲染。路徑會閉環,因此繪製出了Shape
用於CAShapeLayer
的貝塞爾曲線做爲path
,其path
是一個首尾相接的閉環的曲線,即便該貝塞爾曲線不是一個閉環的曲線
效果圖以下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
- (CAShapeLayer *)drawCircle { CAShapeLayer *circleLayer = [CAShapeLayer layer]; // 指定frame,只是爲了設置寬度和高度 circleLayer.frame = CGRectMake(0, 0, 200, 200); // 設置居中顯示 circleLayer.position = self.view.center; // 設置填充顏色 circleLayer.fillColor = [UIColor clearColor].CGColor; // 設置線寬 circleLayer.lineWidth = 2.0; // 設置線的顏色 circleLayer.strokeColor = [UIColor redColor].CGColor;
// 使用UIBezierPath建立路徑 CGRect frame = CGRectMake(0, 0, 200, 200); UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:frame];
// 設置CAShapeLayer與UIBezierPath關聯 circleLayer.path = circlePath.CGPath;
// 將CAShaperLayer放到某個層上顯示 [self.view.layer addSublayer:circleLayer];
return circleLayer; }
|
注意,咱們這裏不是放在-drawRect:
方法中調用的。咱們直接將這個CAShaperLayer
放到了self.view.layer
上,直接呈現出來。
咱們建立一個CAShapeLayer
,而後配置相關屬性,而後再經過UIBezierPath
的類方法建立一個內切圓路徑,而後將路徑指定給CAShapeLayer.path
,這就將二者關聯起來了。最後,將這個層放到了self.view.layer
上呈現出來。
效果圖相似這樣(懶本身作圖,就百度了一個):
咱們調用了上面這個畫圓效果的代碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
- (void)drawHalfCircle { self.loadingLayer = [self drawCircle];
// 這個是用於指定畫筆的開始與結束點 self.loadingLayer.strokeStart = 0.0; self.loadingLayer.strokeEnd = 0.75;
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateCircle) userInfo:nil repeats:YES]; }
- (void)updateCircle { if (self.loadingLayer.strokeEnd > 1 && self.loadingLayer.strokeStart < 1) { self.loadingLayer.strokeStart += 0.1; } else if (self.loadingLayer.strokeStart == 0) { self.loadingLayer.strokeEnd += 0.1; }
if (self.loadingLayer.strokeEnd == 0) { self.loadingLayer.strokeStart = 0; }
if (self.loadingLayer.strokeStart >= 1 && self.loadingLayer.strokeEnd >= 1) { self.loadingLayer.strokeStart = 0; [self.timer invalidate]; self.timer = nil; } }
|
咱們要實現這個效果,是經過strokeStar
和strokeEnd
這兩個屬性來完成的,看看官方說明:
1 2 3 4 5 6 7 8 9 10 11 |
/* These values define the subregion of the path used to draw the * stroked outline. The values must be in the range [0,1] with zero * representing the start of the path and one the end. Values in * between zero and one are interpolated linearly along the path * length. strokeStart defaults to zero and strokeEnd to one. Both are * animatable. */
@property CGFloat strokeStart; @property CGFloat strokeEnd;
|
這裏說明了這兩個值的範圍是[0,1],當strokeStart
的值爲0慢慢變成1時,咱們看到路徑是慢慢消失的。這裏實現的效果並很差,由於不能一塊兒循環着。不過,在這裏學習的目的已經達到了,後面學習動畫效果時,才專門學習它。
小夥伴們能夠到github下載:https://github.com/CoderJackyHuang/UIBezierPathLayerDemos
要測試哪一種效果,就打開對應的註釋就能夠了。