UIBezierPath用於定義一個由直線/曲線組合而成的路徑, 並且可以在自定義視圖中渲染該路徑. 在使用的過程中, 我們只需要先指定好路徑的結構, 比如一條直線、一條貝塞爾曲線、一個矩形、一個橢圓、一個圓弧等, 然後使用系統為我們提供的方法將構建好的路徑渲染出來即可
UIBezierPath位於UIKit庫中, 是針對Core Graphics庫中的CGPathRef的封裝, 其已經可以幫助我們實現一般需求, 下面讓我們一起學習一下UIBezierPath的使用方法
注: 使用UIBezierPath繪畫的代碼寫在自定義視圖的drawRect:方法中
- (void)drawRect:(CGRect)rect { // Drawing code }
初始化一個UIBezierPath對象
UIBezierPath *path = [UIBezierPath bezierPath];
以"矩形路徑"初始化一個UIBezierPath對象
// 參數一: 矩形范圍 UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(20, 20, 200, 100)];
以"內切於一個矩形的橢圓路徑"初始化一個UIBezierPath對象
// 參數一: 矩形范圍 UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(20, 20, 200, 100)];
以"圓角矩形路徑"初始化一個UIBezierPath對象
// 參數一: 矩形范圍 // 參數二: 圓角半徑, 如果半徑大於矩形短邊的一半, 則按照一半處理 UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 20, 200, 100) cornerRadius:30];
以"可選圓弧位置的圓角矩形路徑"初始化一個UIBezierPath對象
// 參數一: 矩形范圍 // 參數二: 圓弧位置, 可以多選 // 參數三: 圓弧半徑, 如果半徑大於矩形短邊的一半, 則按照一半處理, CGSize以小的為准(自己試的, 文檔沒說) UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 20, 200, 100) byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(30, 50)];
以"圓弧路徑"初始化一個UIBezierPath對象
// 參數一: 圓弧圓心 // 參數二: 圓弧半徑 // 參數三: 開始弧度 // 參數四: 結束弧度 // 參數五: 是否為順時針 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:50 startAngle:0 endAngle:M_PI clockwise:YES];坐標系統
將當前點移動到指定的位置
UIBezierPath *path = [UIBezierPath bezierPath]; // 參數一: 指定的位置 [path moveToPoint:CGPointMake(20, 20)];
在路徑中增加一條直線
UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(20, 20)]; // 參數一: 直線的終點位置 [path addLineToPoint:CGPointMake(100, 100)];
在路徑中增加一條圓弧
UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(20, 20)]; [path addLineToPoint:CGPointMake(100, 20)]; // 參數一: 圓弧圓心 // 參數二: 圓弧半徑 // 參數三: 開始弧度 // 參數四: 結束弧度 // 參數五: 是否為順時針 [path addArcWithCenter:CGPointMake(60, 20) radius:40 startAngle:0 endAngle:M_PI clockwise:YES];
在路徑中增加一條二次貝塞爾曲線
UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(20, 20)]; // 參數一: 曲線的終點位置 // 參數二: 控制點 [path addQuadCurveToPoint:CGPointMake(100, 20) controlPoint:CGPointMake(100, 60)];二次貝塞爾曲線
在路徑中增加一條三次貝塞爾曲線
UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(20, 20)]; // 參數一: 曲線的終點位置 // 參數二: 第一控制點 // 參數三: 第二控制點 [path addCurveToPoint:CGPointMake(100, 20) controlPoint1:CGPointMake(30, 60) controlPoint2:CGPointMake(100, 100)];三次貝塞爾曲線
是否路徑信息為空, 即使通過moveToPoint:移動到指定的位置也算不為空
UIBezierPath *path = [UIBezierPath bezierPath]; BOOL isEmpty = path.empty;
可以封閉所有路徑點的最小矩形范圍, 包括多次貝塞爾曲線的控制點在內
UIBezierPath *path = [UIBezierPath bezierPath]; CGRect bounds = path.bounds;
路徑當前所在點
UIBezierPath *path = [UIBezierPath bezierPath]; CGPoint currentPoint = path.currentPoint;
是否包含指定點
UIBezierPath *path = [UIBezierPath bezierPath]; BOOL isContainsPoint = [path containsPoint:CGPointMake(20, 30)];
使用一條直線閉合路徑的起點和終點, 該方法同時也會更新當前點到新直線的終點(即路徑的起點)
UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(20, 20)]; [path addLineToPoint:CGPointMake(100, 100)]; [path addLineToPoint:CGPointMake(100, 200)]; [path closePath];
移除路徑中所有的點
UIBezierPath *path = [UIBezierPath bezierPath]; [path removeAllPoints];
路徑中增加一個已有路徑
UIBezierPath *path = [UIBezierPath bezierPath]; UIBezierPath *path2 = [UIBezierPath bezierPath]; [path appendPath:path2];
返回一個翻轉已有路徑的新路徑
UIBezierPath *path = [UIBezierPath bezierPath]; UIBezierPath *path2 = [path bezierPathByReversingPath];
利用當前繪畫屬性填充路徑封閉范圍, 該方法在繪畫之前會自動將開放子路徑封閉, 填充部分不包含路徑本身, 所以對於線寬較大的路徑, 填充部分會跟部分路徑重合
UIBezierPath *path = [UIBezierPath bezierPath]; // do something.... [path fill];
利用指定模式填充路徑封閉范圍, 該方法在繪畫之前會自動將開放子路徑封閉, 填充部分不包含路徑本身, 所以對於線寬較大的路徑, 填充部分會跟部分路徑重合
UIBezierPath *path = [UIBezierPath bezierPath]; // do something.... [path fillWithBlendMode:kCGBlendModeNormal alpha:0.8];
利用當前繪畫屬性沿著路徑畫線
UIBezierPath *path = [UIBezierPath bezierPath]; // do something.... [path stroke];
利用指定模式沿著路徑畫線
UIBezierPath *path = [UIBezierPath bezierPath]; // do something.... [path strokeWithBlendMode:kCGBlendModeNormal alpha:0.8];
路徑的線寬
UIBezierPath *path = [UIBezierPath bezierPath]; path.lineWidth = 10;
路徑的填充顏色
[[UIColor orangeColor] setFill];
路徑的畫線顏色
[[UIColor orangeColor] setStroke];
路徑的終點形狀, 該屬性適用於開放路徑的起點和終點, 默認為kCGLineCapButt(方形結束, 結束位置正好為精確位置), 其他可選項為kCGLineCapRound(圓形結束, 結束位置超過精確位置半個線寬)和kCGLineCapSquare(方形結束, 結束位置超過精確位置半個線寬)
UIBezierPath *path = [UIBezierPath bezierPath]; path.lineCapStyle = kCGLineCapButt;
路徑的連接點形狀, 默認為kCGLineJoinMiter(全部連接), 其他可選項為kCGLineJoinRound(圓形連接)和kCGLineJoinBevel(斜角連接)
UIBezierPath *path = [UIBezierPath bezierPath]; path.lineJoinStyle = kCGLineJoinMiter;
對路徑中的所有點進行二維形變, 該變化立即生效, 且為永久性改變所有點
UIBezierPath *path = [UIBezierPath bezierPath]; [path applyTransform:CGAffineTransformMakeTranslation(20, 20)];
以"今日頭條下拉刷新效果"為例, 練習一下繪畫方式
CGAffineTransform transform = CGAffineTransformMakeTranslation((self.bounds.size.width-50*5)/2, 100); transform = CGAffineTransformScale(transform, 5, 5); UIBezierPath *path1 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 50, 50) cornerRadius:10]; [path1 applyTransform:transform]; [[UIColor colorWithRed:198/255.0f green:198/255.0f blue:198/255.0f alpha:1.0f] setStroke]; [path1 stroke]; UIBezierPath *path2 = [UIBezierPath bezierPathWithRect:CGRectMake(7, 10, 14, 12)]; [path2 applyTransform:transform]; [[UIColor colorWithRed:224/255.0f green:224/255.0f blue:224/255.0f alpha:1.0f] setFill]; [path2 fill]; UIBezierPath *path3 = [UIBezierPath bezierPathWithRect:CGRectMake(7, 10, 14, 12)]; [path3 applyTransform:transform]; [[UIColor colorWithRed:189/255.0f green:189/255.0f blue:189/255.0f alpha:1.0f] setStroke]; [path3 stroke]; UIBezierPath *path11 = [UIBezierPath bezierPath]; [path11 moveToPoint:CGPointMake(28, 10)]; [path11 addLineToPoint:CGPointMake(43, 10)]; [path11 applyTransform:transform]; [[UIColor colorWithRed:153/255.0f green:153/255.0f blue:153/255.0f alpha:1.0f] setStroke]; [path11 stroke]; UIBezierPath *path12 = [UIBezierPath bezierPath]; [path12 moveToPoint:CGPointMake(28, 16)]; [path12 addLineToPoint:CGPointMake(43, 16)]; [path12 applyTransform:transform]; [path12 stroke]; UIBezierPath *path13 = [UIBezierPath bezierPath]; [path13 moveToPoint:CGPointMake(28, 22)]; [path13 addLineToPoint:CGPointMake(43, 22)]; [path13 applyTransform:transform]; [path13 stroke]; UIBezierPath *path21 = [UIBezierPath bezierPath]; [path21 moveToPoint:CGPointMake(7, 28)]; [path21 addLineToPoint:CGPointMake(43, 28)]; [path21 applyTransform:transform]; [path21 stroke]; UIBezierPath *path22 = [UIBezierPath bezierPath]; [path22 moveToPoint:CGPointMake(7, 34)]; [path22 addLineToPoint:CGPointMake(43, 34)]; [path22 applyTransform:transform]; [path22 stroke]; UIBezierPath *path23 = [UIBezierPath bezierPath]; [path23 moveToPoint:CGPointMake(7, 40)]; [path23 addLineToPoint:CGPointMake(43, 40)]; [path23 applyTransform:transform]; [path23 stroke];今日頭條示例