CAShapeLayer和UIBezierPath
一:貝塞爾曲線 UIBezierPath
使用UIBezierPath類可以創(chuàng)建基于矢量的路徑,這個(gè)類再UIKit中。此類是Core Graphics框架關(guān)于path的一個(gè)封裝。使用此類可以定義簡(jiǎn)單的形狀,如橢圓或者矩形,或者有多個(gè)直線和曲線段組成的形狀。
1、UIBezierPath基礎(chǔ)
UIBezierPath對(duì)象是CGPathRef數(shù)據(jù)類型的封裝。path如果是基于矢量形狀的,都是直線和曲線段去創(chuàng)建。我們使用只線段去創(chuàng)建矩形和多邊形,使用曲線段去創(chuàng)建弧(arc),圓或者其他復(fù)雜的曲線形狀。每一段都包括一個(gè)或者多個(gè)點(diǎn),繪圖命令定義如何詮釋這些點(diǎn)。每一個(gè)直線段或者曲線段的結(jié)束的地方是下一個(gè)的開始的地方。每一個(gè)連接的直線或者曲線段的集合成為subPath。一個(gè)UIBezierPath對(duì)象定義一個(gè)完整的路徑包括一個(gè)或者多個(gè)subpaths。
創(chuàng)建和使用一個(gè)path對(duì)象的過程是分開的。創(chuàng)建path是第一步,包含以下步驟:
- (1)、創(chuàng)建一個(gè)UIBezierPath對(duì)象;
- (2)、使用方法moveToPoint:去設(shè)置初始線段的起點(diǎn);
- (3)、添加line或者curve去定義一個(gè)或者多個(gè)subpaths;
- (4)、改變UIBezierPath對(duì)象跟繪圖相關(guān)的屬性。
例如:我們呢可以設(shè)置strokedPath的屬性lineWidth和lineJoinStyle。也可以設(shè)置filledPath的屬性u(píng)sersEvenOddFullRule。
當(dāng)創(chuàng)建path,我們應(yīng)該管理path上面的點(diǎn)相對(duì)于原點(diǎn)(0,0),這樣我們?cè)陔S后就可以很容易的移動(dòng)path了。為了繪制path對(duì)象,我們要用到stroke和fill方法。這些方法再current graphic context下渲染path的line和curve段。
2、使用UIBezierPath創(chuàng)建多邊形—在path下面添加直線條形成多邊形
多邊形是一些簡(jiǎn)單的形狀,這些形狀是由一些直線線條組成,我們可以用
(1)、 - (void)moveToPoint:(CGPoint)point;
(2)、 - (void)addLineToPoint:(CGPoint)point;
方法去構(gòu)建。
方法moveToPoint:設(shè)置我們想要?jiǎng)?chuàng)建形狀的起點(diǎn)。從這點(diǎn)開始,我們可以用方法addLineToPoint:去創(chuàng)建一個(gè)形狀的線段。
我們可以連續(xù)的創(chuàng)建line,每一個(gè)line的起點(diǎn)都是先前的終點(diǎn),終點(diǎn)就是指定的點(diǎn)。
下面的代碼描述了如何用線段去創(chuàng)建一個(gè)五邊形。第五條線通過調(diào)用 - (void)closePath;方法得到的,它連接了最后一個(gè)點(diǎn)(0,40)和第一個(gè)點(diǎn)(100,0)
說明:closePath方法不僅結(jié)束一個(gè)shape的subpath表述,它也在最后一個(gè)點(diǎn)和第一個(gè)點(diǎn)之間畫一條線段,如果我們畫多邊形的話,這個(gè)一個(gè)便利的方法我們不需要去畫最后一條線。
例如:
3、使用UIBezierPath創(chuàng)建矩形
使用如下方法即可:
+ (UIBezierPath *)bezierPathWithRect:(CGRect)rect;例如:
- (void)drawRect:(CGRect)rect {[super drawRect:rect];UIColor *color = [UIColor redColor];[color set]; //設(shè)置線條顏色UIColor *fillColor = [UIColor yellowColor];[fillColor setFill];UIBezierPath* aPath = [UIBezierPath bezierPathWithRect:CGRectMake(20, 20, 100, 50)];aPath.lineWidth = 5.0;aPath.lineCapStyle = kCGLineCapRound; //線條拐角aPath.lineJoinStyle = kCGLineCapRound; //終點(diǎn)處理[aPath stroke]; }4、使用UIBezierPath創(chuàng)建圓形或者橢圓形
使用這個(gè)方法即可:
+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect;理解:這個(gè)方法根據(jù)傳入的rect矩形參數(shù)繪制一個(gè)內(nèi)切曲線。當(dāng)傳入的rect是一個(gè)正方形時(shí),繪制的圖像是一個(gè)內(nèi)切圓;當(dāng)傳入的rect是一個(gè)長(zhǎng)方形時(shí),繪制的圖像是一個(gè)內(nèi)切橢圓。例如:
- (void)drawRect:(CGRect)rect {[super drawRect:rect];UIColor *color = [UIColor redColor];[color set]; //設(shè)置線條顏色UIColor *fillColor = [UIColor yellowColor];[fillColor setFill];UIBezierPath* aPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(20, 20, 100, 50)];aPath.lineWidth = 5.0;aPath.lineCapStyle = kCGLineCapRound; //線條拐角aPath.lineJoinStyle = kCGLineCapRound; //終點(diǎn)處理[aPath stroke]; }5、使用UIBezierPath創(chuàng)建一段弧線
使用這個(gè)方法:
+ (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;解釋:其中的參數(shù)分別指定:這段圓弧的中心,半徑,開始角度,結(jié)束角度,是否順時(shí)針方向。例如:
#define pi 3.14159265359 #define DEGREES_TO_RADIANS(degrees) ((pi * degrees)/ 180) - (void)drawRect:(CGRect)rect {UIColor *color = [UIColor redColor];[color set]; //設(shè)置線條顏色UIBezierPath* aPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:75 startAngle:0 endAngle:DEGREES_TO_RADIANS(135) clockwise:YES];aPath.lineWidth = 5.0;aPath.lineCapStyle = kCGLineCapRound; //線條拐角aPath.lineJoinStyle = kCGLineCapRound; //終點(diǎn)處理[aPath stroke]; }6、UIBezierPath類提供了添加二次貝塞爾曲線和三次貝塞爾曲線的支持
曲線段在當(dāng)前點(diǎn)開始,在指定的點(diǎn)結(jié)束。曲線的形狀有開始點(diǎn),結(jié)束點(diǎn),一個(gè)或者多個(gè)控制點(diǎn)的切線定義。下圖顯示了兩種曲線類型的相似,以及控制點(diǎn)和curve形狀的關(guān)系。
(1)、繪制二次貝塞爾曲線
使用到這個(gè)方法:
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint; 解釋:其中的參數(shù)分別指定:結(jié)束點(diǎn),控制點(diǎn);
例如:
(2)、繪制三次貝塞爾曲線
使用到這個(gè)方法:
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;解釋:其中的參數(shù)分別指定:結(jié)束點(diǎn),第一個(gè)控制點(diǎn),第二個(gè)控制點(diǎn);
例如:
7、使用Core Graphics函數(shù)去修改path。
UIBezierPath類只是 CGPathRef數(shù)據(jù)類型和path繪圖屬性的一個(gè)封裝。雖然通常我們可以用UIBezierPath類的方法去添加直線段和曲線 段,UIBezierPath類還提供了一個(gè)屬性CGPath,我們可以用來直接修改底層的path data type。如果我們希望用Core Graphics 框架函數(shù)去創(chuàng)建path,則我們要用到此屬性。
有兩種方法可以用來修改和 UIBezierPath對(duì)象相關(guān)的path。可以完全的使用Core Graphics函數(shù)去修改path,也可以使用Core Graphics函數(shù)和UIBezierPath函數(shù)混合去修改。第一種方法在某些方面相對(duì)來說比較容易。我們可以創(chuàng)建一個(gè)CGPathRef數(shù)據(jù)類型, 并調(diào)用我們需要修改path信息的函數(shù)。
下面的代碼就是賦值一個(gè)新的CGPathRef給UIBezierPath對(duì)象。
例如:
如果我們使用Core Graphics函數(shù)和UIBezierPath函數(shù)混合方法,我們必須小心的移動(dòng)path 信息在兩者之間。因?yàn)閁IBezierPath類擁有自己底層的CGPathRef data type,我們不能簡(jiǎn)單的檢索該類型并直接的修改它。相反,我們應(yīng)該生成一個(gè)副本,然后修改此副本,然后賦值此副本給CGPath屬性,如下代碼:
例如:
8、rendering(渲染)Bezier Path對(duì)象的內(nèi)容。
當(dāng)創(chuàng)建一個(gè)UIBezierPath對(duì)象之后,我們可以使用它的stroke和fill方法在current graphics context中去渲染它。在調(diào)用這些方法之前,我們要進(jìn)行一些其他的任務(wù)去確保正確的繪制path。
使用UIColor類的方法去stroke和fill想要的顏色。
設(shè)置形狀在目標(biāo)視圖中的位置。如果我們 創(chuàng)建的path相對(duì)于原點(diǎn)(0,0),則我們可以給current drawing context應(yīng)用一個(gè)適當(dāng)?shù)腶ffie transform。例如,我想drawing一個(gè)形狀起始點(diǎn)在(0,0),我可以調(diào)用函數(shù)CGContextTranslateCTM,并指定水平和垂 直方向的translation值為10。調(diào)整graphic context相對(duì)于調(diào)整path對(duì)象的points是首選的方法,因?yàn)槲覀兛梢院苋菀椎谋4婧统蜂N先前的graphics state。
更新path對(duì)象的drawing 屬性。當(dāng)渲染path時(shí),UIBezierPath實(shí)例的drawing屬性會(huì)覆蓋graphics context下的屬性值。
下面的代碼實(shí)現(xiàn)了在一個(gè)自定義view中實(shí)現(xiàn)drawRect:方法中去繪制一個(gè)橢圓。橢圓邊框矩形的左上角位于視圖坐標(biāo)系統(tǒng)的點(diǎn)(50,50)處。
Drawing a path in a view
例如:
二:CAShapeLayer
1、屬性
(1)、 @property CGPathRef path; 理解:從貝塞爾曲線獲取的形狀; (2)、 @property CGColorRef fillColor; 理解:閉環(huán)填充顏色; (3)、 @property(copy) NSString *fillRule; /* fillRule values. */ CA_EXTERN NSString *const kCAFillRuleNonZero __OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_3_0); CA_EXTERN NSString *const kCAFillRuleEvenOdd __OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_3_0); (4)、 @property CGColorRef strokeColor; 理解:邊緣線的顏色; (5)、 @property CGFloat strokeStart; 理解:控制開始的外觀; (6)、 @property CGFloat strokeEnd; 理解:控制結(jié)束的外觀; (7)、 @property CGFloat lineWidth; 理解:設(shè)置路徑的寬度,默認(rèn)為1; (8)、 @property(copy) NSString *lineCap; 理解:邊緣線的類型; /* lineCap values. */ CA_EXTERN NSString *const kCALineCapButt __OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_3_0); CA_EXTERN NSString *const kCALineCapRound __OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_3_0); CA_EXTERN NSString *const kCALineCapSquare __OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_3_0); (9)、 @property(copy) NSString *lineJoin; 理解:連接方式類型 /* lineJoin values. */ CA_EXTERN NSString *const kCALineJoinMiter __OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_3_0); CA_EXTERN NSString *const kCALineJoinRound __OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_3_0); CA_EXTERN NSString *const kCALineJoinBevel __OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_3_0);2、步驟:
使用CAShapeLayer與UIBezierPath可以實(shí)現(xiàn)不在view的drawRect方法中就畫出一些想要的圖形
- (1)、新建UIBezierPath對(duì)象bezierPath
- (2)、新建CAShapeLayer對(duì)象caShapeLayer
- (3)、將bezierPath的CGPath賦值給caShapeLayer的path,即caShapeLayer.path = bezierPath.CGPath
- (4)、把caShapeLayer添加到某個(gè)顯示該圖形的layer中
三、CAShapeLayer+ CAGradientLayer自定義路徑
使用: @property(strong) CALayer *mask;例如:
#define degreesToRadians(x) (M_PI*(x)/180.0) - (void)viewDidLoad {[super viewDidLoad];UIView* bgView = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 200, 200)];bgView.backgroundColor = [UIColor redColor];[self.view addSubview:bgView];//畫出一個(gè)完成的進(jìn)度的背景軌道//創(chuàng)建一個(gè)路徑圖層CAShapeLayer* trackLayer = [CAShapeLayer layer];trackLayer.frame = bgView.bounds;[bgView.layer addSublayer:trackLayer];trackLayer.fillColor = [[UIColor clearColor] CGColor];//指定path的渲染顏色trackLayer.strokeColor = [[UIColor redColor] CGColor];//背景同學(xué)你就甘心做背景吧,不要太明顯了,透明度小一點(diǎn)trackLayer.opacity = 1;//指定線的邊緣是圓的trackLayer.lineCap = kCALineCapRound;//線的寬度trackLayer.lineWidth = 4;//上面說明過了用來構(gòu)建圓形UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:(200-4)/2 startAngle:degreesToRadians(-210) endAngle:degreesToRadians(30) clockwise:YES];//把path傳遞給layer,然后layer會(huì)處理相應(yīng)的渲染,整個(gè)邏輯和CoreGraph是一致的。trackLayer.path =[path CGPath];//動(dòng)畫CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];animation.duration = 1;animation.fromValue = @(0.0);animation.toValue = @(1.0);[trackLayer addAnimation:animation forKey:@"strokeEnd"];//創(chuàng)建背景圖層CAGradientLayer *gradientLayer = [CAGradientLayer layer];[gradientLayer setColors:[NSArray arrayWithObjects:(id)[[[UIColor blackColor] colorWithAlphaComponent:1] CGColor],(id)[[[UIColor yellowColor] colorWithAlphaComponent:1] CGColor],(id)[[[UIColor blueColor] colorWithAlphaComponent:1] CGColor],(id)[[UIColor clearColor] CGColor],nil]];gradientLayer.frame = bgView.bounds;[gradientLayer setLocations:[NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:0.3],[NSNumber numberWithFloat:0.8],[NSNumber numberWithFloat:1.0],nil]];[gradientLayer setStartPoint:CGPointMake(0, 0.5)];[gradientLayer setEndPoint:CGPointMake(1, 0.5)];[gradientLayer setMask:trackLayer]; //用progressLayer來截取漸變層[bgView.layer addSublayer:gradientLayer]; }總結(jié)
以上是生活随笔為你收集整理的CAShapeLayer和UIBezierPath的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 服务器安全防护措施有什么?网络安全实战
- 下一篇: 物联网——智慧消防云平台