UIBezierPath 全面介紹

UIKit中的UIBezierPath是Core Graphics框架關(guān)于path的一個(gè)封裝??梢詣?chuàng)建基于矢量的路徑,例如橢圓或者矩形,或者有多個(gè)直線和曲線段組成的形狀.

Core Graphics 的基本介紹與使用

屬性:

  • lineWidth:線寬屬性定義了 UIBezierPath 對(duì)象中繪制的曲線規(guī)格. 默認(rèn)為: 1.0
  • lineCapStyle:應(yīng)用于曲線的終點(diǎn)和起點(diǎn). 該屬性在一個(gè)閉合子路經(jīng)中是無(wú)效果的. 默認(rèn)為: kCGLineCapButt

枚舉值:

  typedef CF_ENUM(int32_t, CGLineCap) {
    kCGLineCapButt,
    kCGLineCapRound,
    kCGLineCapSquare
};

對(duì)應(yīng)樣式:

  • lineJoinStyle:曲線連接點(diǎn)的樣式.

枚舉值:

  typedef CF_ENUM(int32_t, CGLineJoin) {
    kCGLineJoinMiter,
    kCGLineJoinRound,
    kCGLineJoinBevel
};

對(duì)應(yīng)樣式:


  • miterLimit:兩條線交匯處內(nèi)角和外角之間的最大距離, 僅當(dāng)連接點(diǎn)樣式為 kCGLineJoinMiter時(shí)生效.
圖解:
  • flatness:渲染精度(表示真實(shí)曲線的點(diǎn)和渲染曲線的點(diǎn)的最大允許距離)。值越小,精度越高。default:0.6。
  • usesEvenOddFillRule:是否使用基偶填充規(guī)則。兩種規(guī)則的詳細(xì)介紹
 設(shè)置為 YES, 則路徑將會(huì)使用 基偶規(guī)則 (even-odd) 進(jìn)行填充.
 設(shè)置為 NO,  則路徑將會(huì)使用 非零規(guī)則 (non-zero) 規(guī)則進(jìn)行填充.
  • CGPath:一個(gè)不可變的 CGPathRef 對(duì)象
他可以傳入 CoreGraphics 提供的函數(shù)中你可以是用 CoreGraphics 框架提供的方法創(chuàng)建一個(gè)路徑, 并給這個(gè)屬性賦值, 當(dāng)時(shí)設(shè)置了一個(gè)新的路徑后, 這個(gè)將會(huì)對(duì)你給出的路徑對(duì)象進(jìn)行 Copy 操作
  • currentPoint:下一條繪制的直線或曲線的起始點(diǎn)。如果當(dāng)前路徑為空, 那么該屬性的值將會(huì)是 CGPointZero
  • bounds:路徑覆蓋的矩形區(qū)域。該屬性描述的是一個(gè)能夠完全包含路徑中所有點(diǎn)的一個(gè)最小的矩形區(qū)域. 該區(qū)域包含二次貝塞爾曲線和三次貝塞爾曲線的控制點(diǎn).
  • empty:路徑是否為空。 <注>: 就算你僅僅調(diào)用了 moveToPoint 方法那么當(dāng)前路徑也被看做不為空.

創(chuàng)建實(shí)例對(duì)象:

  • ? 創(chuàng)建
+ (instancetype) bezierPath;
  • by 矩形
/**
  * 該方法將會(huì)創(chuàng)建一個(gè)閉合路徑, 起始點(diǎn)是 rect 參數(shù)的的 origin, 并且按照順時(shí)針?lè)较蛱砑又本€, 最終形成矩形
  * @param rect:   矩形路徑的 Frame
  */
+ (instancetype)bezierPathWithRect:(CGRect)rect;
  • by 橢圓
/**
  * 該方法將會(huì)創(chuàng)建一個(gè)閉合路徑,  該方法會(huì)通過(guò)順時(shí)針的繪制貝塞爾曲線, 繪制出一個(gè)近似橢圓的形狀. 如果 rect 參數(shù)指定了一個(gè)矩形, 那么該 UIBezierPath 對(duì)象將會(huì)描述一個(gè)圓形.
  * @param rect:   矩形路徑的 Frame
  */
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
  • by 圓角矩形:
/**
  * 該方法將會(huì)創(chuàng)建一個(gè)閉合路徑,  該方法會(huì)順時(shí)針?lè)较蜻B續(xù)繪制直線和曲線.  當(dāng) rect 為正方形時(shí)且 cornerRadius 等于邊長(zhǎng)一半時(shí), 則該方法會(huì)描述一個(gè)圓形路徑.
  * @param rect:   矩形路徑的 Frame
  * @param cornerRadius:   矩形的圓角半徑
  */
+ (instancetype) bezierPathWithRoundedRect:(CGRect)rect 
                              cornerRadius:(CGFloat)cornerRadius;

可以指定矩形的哪個(gè)角為圓角:

/**
  * 該方法將會(huì)創(chuàng)建一個(gè)閉合路徑,  該方法會(huì)順時(shí)針?lè)较蜻B續(xù)繪制直線和曲線.  
  * @param rect:   矩形路徑的 Frame
  * @param corners:   UIRectCorner 枚舉類(lèi)型, 指定矩形的哪個(gè)角變?yōu)閳A角
  * @param cornerRadii:   矩形的圓角半徑
  */
+ (instancetype) bezierPathWithRoundedRect:(CGRect)rect 
                         byRoundingCorners:(UIRectCorner)corners
                               cornerRadii:(CGSize)cornerRadii;
  • by 圓弧
/**
  * 該方法會(huì)創(chuàng)建出一個(gè)開(kāi)放路徑, 創(chuàng)建出來(lái)的圓弧是圓的一部分. 在默認(rèn)的坐標(biāo)系統(tǒng)中, 開(kāi)始角度 和 結(jié)束角度 都是基于單位圓的(看下面這張圖). 調(diào)用這個(gè)方法之后, currentPoint 將會(huì)設(shè)置為圓弧的結(jié)束點(diǎn).
  * 舉例來(lái)說(shuō): 指定其實(shí)角度為0, 指定結(jié)束角度為π, 設(shè)置 clockwise 屬性為 YES, 將會(huì)繪制出圓的下半部分.
  * 然而當(dāng)我們不修改起始角度 和 結(jié)束角度, 我們僅僅將 clockwise 角度設(shè)置為 NO, 則會(huì)繪制出來(lái)一個(gè)圓的上半部分.
  * @param center:   圓心
  * @param radius: 半徑
  * @param startAngle:   起始角度
  * @param endAngle:   結(jié)束角度
  * @param clockwise:   是否順時(shí)針繪制
  */
+ (instancetype) bezierPathWithArcCenter:(CGPoint)center 
                                  radius:(CGFloat)radius 
                              startAngle:(CGFloat)startAngle 
                                endAngle:(CGFloat)endAngle 
                               clockwise:(BOOL)clockwise;

)

  • by CGPath
+ (instancetype) bezierPathWithCGPath:(CGPathRef)CGPath;
  • by 反方向Path(這里的方向是指繪制方向)。
/**
  * @return: 返回一個(gè)新的 UIBezierPath 對(duì)象, 形狀和原來(lái)路徑的形狀一樣,
  *          但是繪制的方向相反.
  */
- (UIBezierPath *) bezierPathByReversingPath;

構(gòu)造或添加路徑:

  • 將對(duì)象的currentPoint移到某個(gè)點(diǎn)。(對(duì)于大多數(shù)構(gòu)造路徑相關(guān)的方法而言, 在你繪制直線或曲線之前, 需要先調(diào)用這個(gè)方法.)
/**
  * 如果當(dāng)前有正在繪制的子路徑, 該方法則會(huì)隱式的結(jié)束當(dāng)前路徑, 
  * 并將 currentPoint 設(shè)置為指定點(diǎn). 當(dāng)上一條子路徑被終止, 該方法
  * 實(shí)際上并不會(huì)去閉合上一條子路徑. 所以上一條自路徑的起始點(diǎn) 和
  * 結(jié)束點(diǎn)并沒(méi)有被鏈接.
  * @param point:   當(dāng)前坐標(biāo)系統(tǒng)中的某一點(diǎn)
  */
- (void)moveToPoint:(CGPoint)point;
  • 追加 一條直線
/**
  * 該方法將會(huì)從 currentPoint 到 指定點(diǎn) 鏈接一條直線. 
  * Note: 在追加完這條直線后, 該方法將會(huì)更新 currentPoint 為 指定點(diǎn)
  *       調(diào)用該方法之前, 你必須先設(shè)置 currentPoint. 如果當(dāng)前繪制路徑
  *       為空, 并且未設(shè)置 currentPoint, 那么調(diào)用該方法將不會(huì)產(chǎn)生任何
  *       效果.
  * @param point:   繪制直線的終點(diǎn)坐標(biāo), 當(dāng)前坐標(biāo)系統(tǒng)中的某一點(diǎn)
  */
- (void)addLineToPoint:(CGPoint)point;
  • 追加 一條圓弧
/**
  * 該方法將會(huì)從 currentPoint 添加一條指定的圓弧.
  * 該方法的介紹和構(gòu)造方法中的一樣. 請(qǐng)前往上文查看
  * @param center: 圓心
  * @param radius: 半徑
  * @param startAngle: 起始角度
  * @param endAngle: 結(jié)束角度
  * @param clockwise: 是否順時(shí)針繪制
  */
- (void)addArcWithCenter:(CGPoint)center 
                  radius:(CGFloat)radius 
              startAngle:(CGFloat)startAngle 
                endAngle:(CGFloat)endAngle 
               clockwise:(BOOL)clockwise NS_AVAILABLE_IOS(4_0);
  • 追加 一條三次貝塞爾曲線
/**
  * 該方法將會(huì)從 currentPoint 到 指定的 endPoint 追加一條三次貝塞爾曲線.
  * 三次貝塞爾曲線的彎曲由兩個(gè)控制點(diǎn)來(lái)控制. 如下圖所示
  * Note: 調(diào)用該方法前, 你必須先設(shè)置 currentPoint, 如果路徑為空, 
  *       并且尚未設(shè)置 currentPoint, 調(diào)用該方法則不會(huì)產(chǎn)生任何效果. 
  *       當(dāng)添加完貝塞爾曲線后, 該方法將會(huì)自動(dòng)更新 currentPoint 為
  *       指定的結(jié)束點(diǎn)
  * @param endPoint: 終點(diǎn)
  * @param controlPoint1: 控制點(diǎn)1
  * @param controlPoint2: 控制點(diǎn)2
  */
- (void)addCurveToPoint:(CGPoint)endPoint 
          controlPoint1:(CGPoint)controlPoint1 
          controlPoint2:(CGPoint)controlPoint2;
圖解:

)

  • 追加一條二次貝塞爾曲線
/**
  * 該方法將會(huì)從 currentPoint 到 指定的 endPoint 追加一條二次貝塞爾曲線.
  * currentPoint、endPoint、controlPoint 三者的關(guān)系最終定義了二次貝塞爾曲線的形狀.
  * 二次貝塞爾曲線的彎曲由一個(gè)控制點(diǎn)來(lái)控制. 如下圖所示
  * Note: 調(diào)用該方法前, 你必須先設(shè)置 currentPoint, 如果路徑為空, 
  *       并且尚未設(shè)置 currentPoint, 調(diào)用該方法則不會(huì)產(chǎn)生任何效果. 
  *       當(dāng)添加完貝塞爾曲線后, 該方法將會(huì)自動(dòng)更新 currentPoint 為
  *       指定的結(jié)束點(diǎn)
  * @param endPoint: 終點(diǎn)
  * @param controlPoint: 控制點(diǎn)
  */
- (void)addQuadCurveToPoint:(CGPoint)endPoint 
               controlPoint:(CGPoint)controlPoint;
圖解:
  • 追加 UIBezierPath 實(shí)例對(duì)象
/**
  * 該方法將會(huì)在當(dāng)前 UIBezierPath 對(duì)象的路徑中追加
  * 指定的 UIBezierPath 對(duì)象中的內(nèi)容. 
  */
- (void)appendPath:(UIBezierPath *)bezierPath;

虛線路徑:

  • 構(gòu)建一條虛線路徑:
/**
  * @param pattern: 該屬性是一個(gè) C 語(yǔ)言的數(shù)組, 其中每一個(gè)元素都是 CGFloat
  *                 數(shù)組中的元素代表著線段每一部分的長(zhǎng)度, 第一個(gè)元素代表線段的第一條線,
  *                 第二個(gè)元素代表線段中的第一個(gè)間隙. 這個(gè)數(shù)組中的值是輪流的. 來(lái)解釋一下
  *                 什么叫輪流的. 
  *                 舉個(gè)例子: 聲明一個(gè)數(shù)組 CGFloat dash[] = @{3.0, 1.0}; 
  *                 這意味著繪制的虛線的第一部分長(zhǎng)度為3.0, 第一個(gè)間隙長(zhǎng)度為1.0, 虛線的
  *                 第二部分長(zhǎng)度為3.0, 第二個(gè)間隙長(zhǎng)度為1.0. 以此類(lèi)推.

  * @param count: 這個(gè)參數(shù)是 pattern 數(shù)組的個(gè)數(shù)
  * @param phase: 這個(gè)參數(shù)代表著, 虛線從哪里開(kāi)始繪制.
  *                 舉個(gè)例子: 這是 phase 為 6. pattern[] = @{5, 2, 3, 2}; 那么虛線將會(huì)
  *                 第一個(gè)間隙的中間部分開(kāi)始繪制, 如果不是很明白就請(qǐng)繼續(xù)往下看,
  *                 下文實(shí)戰(zhàn)部分會(huì)對(duì)虛線進(jìn)行講解.
  */
- (void)setLineDash:(const CGFloat *)pattern
              count:(NSInteger)count
              phase:(CGFloat)phase;
  • 獲取虛線的模式:
/**
  * 該方法可以重新獲取之前設(shè)置過(guò)的虛線樣式.
  *  Note:  pattern 這個(gè)參數(shù)的容量必須大于該方法返回?cái)?shù)組的容量.
  *         如果無(wú)法確定數(shù)組的容量, 那么可以調(diào)用兩次該方法, 第一次
  *         調(diào)用該方法的時(shí)候, 傳入 count 參數(shù), 然后在用 count 參數(shù)
  *         來(lái)申請(qǐng) pattern 數(shù)組的內(nèi)存空間. 然后再第二次正常的調(diào)用該方法
  */
- (void)getLineDash:(CGFloat *)pattern 
              count:(NSInteger *)count
              phase:(CGFloat *)phase;
Demo:
- (void) typeDashLine {

    // 1. 先創(chuàng)建三條路徑, 有對(duì)比更有助于理解
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint: CGPointMake(80, 40)];
    [path addLineToPoint: CGPointMake(self.frame.size.width - 40, 40)];
    path.lineWidth = 2;


    UIBezierPath *path1 = [UIBezierPath bezierPath];
    [path1 moveToPoint: CGPointMake(80, 80)];
    [path1 addLineToPoint: CGPointMake(self.frame.size.width - 40, 80)];
    path1.lineWidth = 2;


    UIBezierPath *path2 = [UIBezierPath bezierPath];
    [path2 moveToPoint: CGPointMake(80, 120)];
    [path2 addLineToPoint: CGPointMake(self.frame.size.width - 40, 120)];
    path2.lineWidth = 2;

    // 2.  這部分是配置三條路徑虛線的規(guī)格, 重點(diǎn)主要是這部分.
    CGFloat dashLineConfig[] = {8.0, 4.0};
    [path setLineDash: dashLineConfig
                           count: 2
                          phase: 0];


    CGFloat dashLineConfig1[] = {8.0, 4.0, 16.0, 8.0};
    [path1 setLineDash: dashLineConfig1
                count: 4
                phase: 0];


    CGFloat dashLineConfig2[] = {8.0, 4.0, 16.0, 8.0};
    [path2 setLineDash: dashLineConfig2
                count: 4
                phase: 12];

    // 3. 繪制
    [[UIColor orangeColor] set];
    [path stroke];
    [path1 stroke];
    [path2 stroke];
}

顯示效果:

)

更改路徑:

  • 關(guān)閉當(dāng)前子路徑:
/**
  * 該方法將會(huì)從 currentPoint 到子路經(jīng)的起點(diǎn) 繪制一條直線, 
  * 以此來(lái)關(guān)閉當(dāng)前的自路徑. 緊接著該方法將會(huì)更新 currentPoint
  * 為 剛添加的這條直線的終點(diǎn), 也就是當(dāng)前子路經(jīng)的起點(diǎn).
  */
- (void)closePath;
  • 刪除 UIBezierPath 對(duì)象中的所有點(diǎn), 效果也就等同于刪除了所有子路經(jīng):
- (void)removeAllPoints;
  • 剪切路徑:
/**
  *  該方法將會(huì)修改當(dāng)前繪圖上下文的可視區(qū)域.
  *  當(dāng)調(diào)用這個(gè)方法之后, 會(huì)導(dǎo)致接下來(lái)所有的渲染
  *  操作, 只會(huì)在剪切下來(lái)的區(qū)域內(nèi)進(jìn)行, 區(qū)域外的
  *  內(nèi)容將不會(huì)被渲染.
  *  如果你希望執(zhí)行接下來(lái)的繪圖時(shí), 刪除剪切區(qū)域,
  *  那么你必須在調(diào)用該方法前, 先使用 CGContextSaveGState 方法
  *  保存當(dāng)前的繪圖狀態(tài), 當(dāng)你不再需要這個(gè)剪切區(qū)域
  *  的時(shí)候, 你只需要使用 CGContextRestoreGState 方法
  *  來(lái)恢復(fù)之前保存的繪圖狀態(tài)就可以了.
  * @param blendMode: 混合模式?jīng)Q定了如何和
  *                   已經(jīng)存在的被渲染過(guò)的內(nèi)容進(jìn)行合成
  * @param alpha: 填充路徑時(shí)的透明度
  */
- (void)addClip;
  • 放射變換操作:
/**
  * 該方法將會(huì)直接對(duì)路徑中的所有點(diǎn)進(jìn)行指定的放射
  * 變換操作. 
  */
- (void)applyTransform:(CGAffineTransform)transform;

繪制相關(guān):

  • 填充路徑:
/**
  * 該方法當(dāng)前的填充顏色 和 繪圖屬性對(duì)路徑的封閉區(qū)域進(jìn)行填充.
  * 如果當(dāng)前路徑是一條開(kāi)放路徑, 該方法將會(huì)隱式的將路徑進(jìn)行關(guān)閉后進(jìn)行填充
  * 該方法在進(jìn)行填充操作之前, 會(huì)自動(dòng)保存當(dāng)前繪圖的狀態(tài), 所以我們不需要
  * 自己手動(dòng)的去保存繪圖狀態(tài)了. 
  */
- (void)fill;
  • 使用混合模式填充路徑:
/**
  * 該方法當(dāng)前的填充顏色 和 繪圖屬性 (外加指定的混合模式 和 透明度) 
  * 對(duì)路徑的封閉區(qū)域進(jìn)行填充. 如果當(dāng)前路徑是一條開(kāi)放路徑, 該方法將
  * 會(huì)隱式的將路徑進(jìn)行關(guān)閉后進(jìn)行填充
  * 該方法在進(jìn)行填充操作之前, 會(huì)自動(dòng)保存當(dāng)前繪圖的狀態(tài), 所以我們不需要
  * 自己手動(dòng)的去保存繪圖狀態(tài)了. 
  *
  * @param blendMode: 混合模式?jīng)Q定了如何和已經(jīng)存在的被渲染過(guò)的內(nèi)容進(jìn)行合成
  * @param alpha: 填充路徑時(shí)的透明度
  */
- (void)fillWithBlendMode:(CGBlendMode)blendMode 
                    alpha:(CGFloat)alpha;
  • 繪制路徑:(一般用于將路徑相關(guān)設(shè)置完成后的最后一步操作).
- (void)stroke;

判斷方法:

  • 是否包含某個(gè)點(diǎn):
/**
  *  該方法返回一個(gè)布爾值, 當(dāng)曲線的覆蓋區(qū)域包含
  * 指定的點(diǎn)(內(nèi)部點(diǎn)), 則返回 YES, 否則返回 NO. 
  * Note: 如果當(dāng)前的路徑是一個(gè)開(kāi)放的路徑, 那么
  *       就算指定點(diǎn)在路徑覆蓋范圍內(nèi), 該方法仍然會(huì)
  *       返回 NO, 所以如果你想判斷一個(gè)點(diǎn)是否在一個(gè)
  *       開(kāi)放路徑的范圍內(nèi)時(shí), 你需要先Copy一份路徑,
  *       并調(diào)用 -(void)closePath; 將路徑封閉, 然后
  *       再調(diào)用此方法來(lái)判斷指定點(diǎn)是否是內(nèi)部點(diǎn).
  * @param point: 指定點(diǎn).
  */
- (BOOL) containsPoint:(CGPoint)point;

Demo實(shí)例:

  • 屬性方法簡(jiǎn)單應(yīng)用:
    
    //========================================================
    //>>>Part one : 創(chuàng)建UIBezierPath對(duì)象。
    //========================================================
    
    //1、通過(guò)矩形:
    UIBezierPath * rectPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 30, 50)];
    /**
     判斷相關(guān):
     */
    //ONE:是否包含。
    BOOL isContain = [rectPath containsPoint:CGPointMake(25, 24)];
    if (isContain) {
        NSLog(@"contain");
    }
    //TWO:路徑是否為空。
    BOOL isEmpty = [rectPath isEmpty];
    if (!isEmpty) {
        NSLog(@"not empty");
    }
    
    /**
     相關(guān)屬性:
     */
    rectPath.lineWidth = 3;
    rectPath.lineCapStyle = kCGLineCapSquare; //曲線終點(diǎn)樣式,不適用于閉合路徑。
    rectPath.lineJoinStyle = kCGLineJoinMiter;  //曲線連接樣式。
    rectPath.miterLimit = 2; //內(nèi)外角最大距離。
    rectPath.flatness = 0.6; //默認(rèn)0.6,越低精度越高。
    rectPath.usesEvenOddFillRule = YES; //是否適用奇偶填充規(guī)則。默認(rèn)非零規(guī)則填充。
    NSLog(@"覆蓋的矩形區(qū)域:%@",[NSValue valueWithCGRect:rectPath.bounds]);//判斷覆蓋的矩形區(qū)域
    
    [[UIColor orangeColor]set];
    [rectPath stroke];
    
    //2、通過(guò)橢圓(矩形的內(nèi)切橢圓)
    UIBezierPath * ovalPath= [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 70, 30, 50)];
    [[UIColor redColor]set];
    [ovalPath stroke];
    
    //3、通過(guò)圓角矩形:
    UIBezierPath * cornerRectPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 130, 30, 50) cornerRadius:3];
    [[UIColor blackColor] set];
    [cornerRectPath stroke];
    
    //4、通過(guò)圓弧:
    UIBezierPath * arcPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(60, 200) radius:50 startAngle:M_PI_2 endAngle:M_PI clockwise:YES];
    [[UIColor brownColor] set];
    arcPath.lineWidth = 4;
    [arcPath stroke];
    
    //5、通過(guò)path。
    CGPathRef  pathRef = CGPathCreateWithRect(CGRectMake(0, 280, 30, 50), nil);
    UIBezierPath * pathPath = [UIBezierPath bezierPathWithCGPath:pathRef];
    [[UIColor redColor]set];
    [pathPath stroke];
    
    
    //========================================================
    //>>>Part two:構(gòu)造路徑:
    //========================================================
    UIBezierPath * allocPath = [UIBezierPath bezierPath];
    allocPath.lineWidth= 4;
    [allocPath moveToPoint:CGPointMake(50, 350)];
    
    //追加一條直線路徑:
//    [allocPath addLineToPoint:CGPointMake(50, 400)];
    
    //追加一條圓?。?當(dāng)起始點(diǎn)到圓心的距離大于半徑的時(shí)候,起始點(diǎn)到距離圓心半徑的點(diǎn)上會(huì)作一條直線)
//    [allocPath addArcWithCenter:CGPointMake(50, 400) radius:50 startAngle:M_PI_2+M_PI endAngle:M_PI_2 clockwise:NO];
    
    //追加一條三次貝塞爾曲線:
//    [allocPath addCurveToPoint:CGPointMake(50, 400) controlPoint1:CGPointMake(60, 370) controlPoint2:CGPointMake(30, 385)];
    
    //追加一條二次貝塞爾曲線;
    [allocPath addQuadCurveToPoint:CGPointMake(50, 400) controlPoint:CGPointMake(30, 385)];
    //關(guān)閉路徑:
    [allocPath closePath];
    //刪除所有點(diǎn):
//    [allocPath removeAllPoints];
    //添加一個(gè)路徑到當(dāng)前路徑中來(lái)。
//    [allocPath appendPath:pathPath];
    //填充;
//    [allocPath fill];
    //選擇將以何種混合方式進(jìn)行填充。//?
//    [allocPath fillWithBlendMode:kCGBlendModeLighten alpha:0.8];
    
    
    
    [[UIColor orangeColor] set];
    [allocPath stroke];
    
    
    [[UIColor redColor]setFill];
    
    UIRectFill(CGRectMake(100, 50, 100, 50));
    

CAShapeLayer

屬性:

大多屬性和UIBezierPath的屬性類(lèi)似。

  • path: CGPathRef 對(duì)象,圖形邊線路徑。

  • fillColor:CGColorRef對(duì)象,圖形填充色,默認(rèn)為黑色。

  • fillRule:填充規(guī)則。類(lèi)似于UIBezierPath的fillMode屬性。

kCAFillRuleNonZero : 非零環(huán)繞數(shù)規(guī)則。

這個(gè)規(guī)則通過(guò)從canvas上的某個(gè)點(diǎn)往任一方向繪制射線到無(wú)窮遠(yuǎn),然后檢查圖形的線段和射線相交的點(diǎn),來(lái)確定“內(nèi)部區(qū)域”。從0開(kāi)始計(jì)數(shù),每次路徑線段是從左到右穿過(guò)射線就加一,從右到左的就減一。通過(guò)計(jì)算交叉點(diǎn),如果結(jié)果是0,則這個(gè)點(diǎn)在路徑外邊,不然,就是在里邊。

[圖片上傳失敗...(image-4ee41e-1552033143799)]

kCAFillRuleEvenOdd : 奇偶原則。

通過(guò)從canvas上某個(gè)點(diǎn)往任一方向繪制射線到無(wú)窮遠(yuǎn),然后計(jì)算給定圖形上線段路徑和該射線交叉點(diǎn)的數(shù)量。如果這個(gè)數(shù)是奇數(shù),那么該點(diǎn)在圖形內(nèi)部;如果是偶數(shù),該點(diǎn)在圖形外部。

[圖片上傳失敗...(image-53b934-1552033143799)]

  • strokeColor:邊線顏色。

  • lineDashPhase:邊線樣式的起始位置,即,如果lineDashPattern設(shè)置為@[2,2,3,4], lineDashPhase即為第一個(gè)長(zhǎng)度為2的線的起始位置。

  • strokeStart,strokeEnd: [0,1]表示畫(huà)邊線的起點(diǎn)和終點(diǎn)。

  • lineDashPattern: NSNumber數(shù)組,依次表示單個(gè)線的長(zhǎng)度和空白的長(zhǎng)度。

DEMO:

    //   創(chuàng)建一個(gè)路徑對(duì)象
    UIBezierPath *linePath = [UIBezierPath bezierPath];
    //  起點(diǎn)
    [linePath moveToPoint:(CGPoint){20,20}];
    // 其他點(diǎn)
    [linePath addLineToPoint:(CGPoint){180,160}];
    [linePath addLineToPoint:(CGPoint){200,50}];
    [linePath addLineToPoint:CGPointMake(250, 250)];
    
    //  設(shè)置路徑畫(huà)布
    CAShapeLayer *lineLayer = [CAShapeLayer layer];
    lineLayer.bounds = (CGRect){0,0,200,200};
    lineLayer.position = CGPointMake(100, 100);
    lineLayer.lineWidth = 2.0;
    lineLayer.strokeColor = [UIColor blueColor].CGColor; //   邊線顏色
    
    lineLayer.path = linePath.CGPath;
    lineLayer.fillColor  = nil;   //  默認(rèn)是black
    
    //  添加到圖層上
    [self.layer addSublayer:lineLayer];

更多Demo可見(jiàn)關(guān)于貝塞爾曲線與CAShapeLayer的學(xué)習(xí)

總結(jié):

UIBezierPath 在當(dāng)前的繪圖上下文中繪制圖形了. 因?yàn)閯?chuàng)建、 配置、 渲染路徑等操作, 都是完全不同的步驟, 所以你可以在你的代碼中非常容易的對(duì)UIBezierPath 對(duì)象進(jìn)行復(fù)用. 你甚至可以使用同一個(gè) UIBezierPath 對(duì)象去渲染同一個(gè)圖形很多次, 你也可以再多次渲染的間隔中, 修改屬性來(lái)渲染出不同樣式的路徑.

當(dāng)你為UIBezierPath 對(duì)象配置完幾何路徑繪圖屬性之后, 你就可以使用strokefill方法在當(dāng)前的繪圖上下文中進(jìn)行繪制了. stroke方法將會(huì)使用當(dāng)前的strokeColor繪圖屬性來(lái)描繪曲線的輪廓. 同樣的, fill 方法將會(huì)使用fillColor 來(lái)填充路徑所圍成的圖形(使用UIColor 類(lèi)方法來(lái)設(shè)置strokeColorfillColor).

本文大量方法理解源于此文UIBezier--簡(jiǎn)書(shū), 感謝文章作者對(duì)UIBezier進(jìn)行了較為全面細(xì)致的分析,提供了大量有關(guān)官方文檔的譯解,使本人受益匪淺。

后續(xù)會(huì)繼續(xù)增進(jìn)有關(guān)UIBezierPath的深入理解及一些靈活運(yùn)用的實(shí)例,屆時(shí)會(huì)補(bǔ)充到本文中。

最后編輯于
?著作權(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)容

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