轉載:UIBezierPath精講
基礎知識
使用UIBezierPath可以建立基於向量的路徑,此類是Core Graphics框架關於路徑的封裝。使用此類可以定義簡單的形狀,如橢圓、矩形或者有多個直線和曲線段組成的形狀等。
UIBezierPath是CGPathRef資料型別的封裝。如果是基於向量形狀的路徑,都用直線和曲線去建立。我們使用直線段去建立矩形和多邊形,使用曲線去建立圓弧(arc)、圓或者其他複雜的曲線形狀。
使用UIBezierPath畫圖步驟:
建立一個UIBezierPath物件
呼叫-moveToPoint:設定初始線段的起點
新增線或者曲線去定義一個或者多個子路徑
改變UIBezierPath物件跟繪圖相關的屬性。如,我們可以設定畫筆的屬性、填充樣式等
UIBezierPath建立方法介紹
我們先看看UIBezierPath類提供了哪些建立方式,這些都是工廠方法,直接使用即可。
+(instancetype)bezierPath;
+(instancetype)bezierPathWithRect:(CGRect)rect;
+(instancetype)bezierPathWithOvalInRect:(CGRect)rect;
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
+(instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
+(instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;
下面我們一個一個地介紹其用途。
+(instancetype)bezierPath;
這個使用比較多,因為這個工廠方法建立的物件,我們可以根據我們的需要任意定製樣式,可以畫任何我們想畫的圖形。
+(instancetype)bezierPathWithRect:(CGRect)rect;
這個工廠方法根據一個矩形畫貝塞爾曲線。
+(instancetype)bezierPathWithOvalInRect:(CGRect)rect;
這個工廠方法根據一個矩形畫內切曲線。通常用它來畫圓或者橢圓。
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius (CGFloat)cornerRadius;
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
第一個工廠方法是畫矩形,但是這個矩形是可以畫圓角的。第一個引數是矩形,第二個引數是圓角大小。 第二個工廠方法功能是一樣的,但是可以指定某一個角畫成圓角。像這種我們就可以很容易地給UIView擴充套件新增圓角的方法了。
+(instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
這個工廠方法用於畫弧,引數說明如下:center: 弧線中心點的座標radius: 弧線所在圓的半徑startAngle: 弧線開始的角度值endAngle: 弧線結束的角度值clockwise: 是否順時針畫弧線
溫馨提示
我們下面的程式碼都是在自定義的BezierPathView類中下面的方法中呼叫:
-(void)drawRect:(CGRect)rect`
畫三角形
先看效果圖:
// 畫三角形
-(void)drawTrianglePath{
UIBezierPath*path=[UIBezierPathbezierPath];
[pathmoveToPoint:CGPointMake(20,20)];
[pathaddLineToPoint:CGPointMake(self.frame.size.width-40,20)];
[pathaddLineToPoint:CGPointMake(self.frame.size.width/2,self.frame.size.height-20)];
// 最後的閉合線是可以通過呼叫closePath方法來自動生成的,也可以呼叫-addLineToPoint:方法來新增
// [path addLineToPoint:CGPointMake(20, 20)];
[pathclosePath];
// 設定線寬
path.lineWidth=1.5;
// 設定填充顏色
UIColor*fillColor=[UIColorgreenColor];
[fillColorset];
[pathfill];
// 設定畫筆顏色
UIColor*strokeColor=[UIColorblueColor];
[strokeColorset];
// 根據我們設定的各個點連線
[pathstroke];
}
我們設定畫筆顏色通過set方法:
UIColor*strokeColor=[UIColorblueColor];
[strokeColorset];
如果我們需要設定填充顏色,比如這裡設定為綠色,那麼我們需要在設定畫筆顏色之前先設定填充顏色,否則畫筆顏色就被填充顏色替代了。也就是說,如果要讓填充顏色與畫筆顏色不一樣,那麼我們的順序必須是先設定填充顏色再設定畫筆顏色。如下,這兩者順序不能改變。因為我們設定填充顏色也是跟設定畫筆顏色一樣呼叫UIColor的-set方法。
// 設定填充顏色
UIColor*fillColor=[UIColorgreenColor];
[fillColorset];
[pathfill];
// 設定畫筆顏色
UIColor*strokeColor=[UIColorblueColor];
[strokeColorset];
畫矩形
先看效果圖:
// 畫矩形
-(void)drawRectPath{
UIBezierPath*path=[UIBezierPathbezierPathWithRect:CGRectMake(20,20,self.frame.size.width-40,self.frame.size.height-40)];
path.lineWidth=1.5;
path.lineCapStyle=kCGLineCapRound;
path.lineJoinStyle=kCGLineJoinBevel;
// 設定填充顏色
UIColor*fillColor=[UIColorgreenColor];
[fillColorset];
[pathfill];
// 設定畫筆顏色
UIColor*strokeColor=[UIColorblueColor];
[strokeColorset];
// 根據我們設定的各個點連線
[pathstroke];
}
lineCapStyle屬性是用來設定線條拐角帽的樣式的,其中有三個選擇:
/* Line cap styles. */
typedefCF_ENUM(int32_t,CGLineCap){
kCGLineCapButt,
kCGLineCapRound,
kCGLineCapSquare
};
其中,第一個是預設的,第二個是輕微圓角,第三個正方形。
lineJoinStyle屬性是用來設定兩條線連結點的樣式,其中也有三個選擇:
/* Line join styles. */
typedefCF_ENUM(int32_t,CGLineJoin){
kCGLineJoinMiter,
kCGLineJoinRound,
kCGLineJoinBevel
};
其中,第一個是預設的表示斜接,第二個是圓滑銜接,第三個是斜角連線。
畫圓
我們可以使用+ bezierPathWithOvalInRect:方法來畫圓,當我們傳的rect引數是一下正方形時,畫出來的就是圓。
先看效果圖:
-(void)drawCiclePath{
// 傳的是正方形,因此就可以繪製出圓了
UIBezierPath*path=[UIBezierPathbezierPathWithOvalInRect:CGRectMake(20,20,self.frame.size.width-40,self.frame.size.width-40)];
// 設定填充顏色
UIColor*fillColor=[UIColorgreenColor];
[fillColorset];
[pathfill];
// 設定畫筆顏色
UIColor*strokeColor=[UIColorblueColor];
[strokeColorset];
// 根據我們設定的各個點連線
[pathstroke];
}
注意:要畫圓,我們需要傳的rect引數必須是正方形哦!
畫橢圓
先看效果圖:
前面我們已經畫圓了,我們可以使用+ bezierPathWithOvalInRect:方法來畫圓,當我們傳的rect引數是一下正方形時,畫出來的就是圓。那麼我們要是不傳正方形,那麼繪製出來的就是橢圓了。
// 畫橢圓
-(void)drawOvalPath{
// 傳的是不是正方形,因此就可以繪製出橢圓圓了
UIBezierPath*path=[UIBezierPathbezierPathWithOvalInRect:CGRectMake(20,20,self.frame.size.width-80,self.frame.size.height-40)];
// 設定填充顏色
UIColor*fillColor=[UIColorgreenColor];
[fillColorset];
[pathfill];
// 設定畫筆顏色
UIColor*strokeColor=[UIColorblueColor];
[strokeColorset];
// 根據我們設定的各個點連線
[pathstroke];
}
畫帶圓角的矩形
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
第一個工廠方法是畫矩形,但是這個矩形是可以畫圓角的。第一個引數是矩形,第二個引數是圓角大小。 第二個工廠方法功能是一樣的,但是可以指定某一個角畫成圓角。像這種我們就可以很容易地給UIView擴充套件新增圓角的方法了。
四個都是圓角10:
-(void)drawRoundedRectPath{
UIBezierPath*path=[UIBezierPathbezierPathWithRoundedRect:CGRectMake(20,20,self.frame.size.width-40,self.frame.size.height-40)cornerRadius:10];
// 設定填充顏色
UIColor*fillColor=[UIColorgreenColor];
[fillColorset];
[pathfill];
// 設定畫筆顏色
UIColor*strokeColor=[UIColorblueColor];
[strokeColorset];
// 根據我們設定的各個點連線
[pathstroke];
}
如果要畫只有一個角是圓角,那麼我們就修改建立方法:
UIBezierPath*path=[UIBezierPathbezierPathWithRoundedRect:CGRectMake(20,20,self.frame.size.width-40,self.frame.size.height-40)byRoundingCorners:UIRectCornerTopRightcornerRadii:CGSizeMake(20,20)];
其中第一個引數一樣是傳了個矩形,第二個引數是指定在哪個方向畫圓角,第三個引數是一個CGSize型別,用來指定水平和垂直方向的半徑的大小。看下效果圖:
畫弧
畫弧前,我們需要了解其參考系,如下圖(圖片來自網路):
#define kDegreesToRadians(degrees) ((pi * degrees)/ 180)
-(void)drawARCPath{
constCGFloatpi=3.14159265359;
CGPointcenter=CGPointMake(self.frame.size.width/2,self.frame.size.height/2);
UIBezierPath*path=[UIBezierPathbezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:kDegreesToRadians(135) clockwise:YES];
path.lineCapStyle=kCGLineCapRound;
path.lineJoinStyle=kCGLineJoinRound;
path.lineWidth=5.0;
UIColor*strokeColor=[UIColorredColor];
[strokeColorset];
[pathstroke];
}
效果圖如下:
我們要明確一點,畫弧引數startAngle和endAngle使用的是弧度,而不是角度,因此我們需要將常用的角度轉換成弧度。對於效果圖中,我們設定弧的中心為控制元件的中心,起點弧度為0,也就是正東方向,而終點是135度角的位置。如果設定的clockwise:YES是逆時針方向繪製,如果設定為NO,效果如下:
這兩者正好是相反的。
畫二次貝塞爾曲線
先來學習一下關於控制點,如下圖(圖片來自網路):
畫二次貝塞爾曲線,是通過呼叫此方法來實現的:
-(void)addQuadCurveToPoint:(CGPoint)endPointcontrolPoint:(CGPoint)controlPoint
引數說明:
endPoint:終端點
controlPoint:控制點,對於二次貝塞爾曲線,只有一個控制點
看效果圖:
-(void)drawSecondBezierPath{
UIBezierPath*path=[UIBezierPathbezierPath];
// 首先設定一個起始點
[pathmoveToPoint:CGPointMake(20,self.frame.size.height-100)];
// 新增二次曲線
[pathaddQuadCurveToPoint:CGPointMake(self.frame.size.width-20,self.frame.size.height-100)
controlPoint:CGPointMake(self.frame.size.width/2,0)];
path.lineCapStyle=kCGLineCapRound;
path.lineJoinStyle=kCGLineJoinRound;
path.lineWidth=5.0;
UIColor*strokeColor=[UIColorredColor];
[strokeColorset];
[pathstroke];
}
畫二次貝塞爾曲線的步驟:
先設定一個起始點,也就是通過-moveToPoint:設定
呼叫-addQuadCurveToPoint:controlPoint:方法設定終端點和控制點,以畫二次曲線
在效果圖中,拱橋左邊的起始點就是我們設定的起始點,最右邊的終點,就是我們設定的終端點,而我們設定的控制點為(width / 2, 0)對應於紅色矩形中水平方向在正中央,而垂直方向在最頂部。
這個樣式看起來很像sin或者cos函式吧?這兩個只是特例而已,其實可以畫任意圖形,只是想不到,沒有做不到的。
畫三次貝塞爾曲線
貝塞爾曲線必定通過首尾兩個點,稱為端點;中間兩個點雖然未必要通過,但卻起到牽制曲線形狀路徑的作用,稱作控制點。關於三次貝塞爾曲線的控制器,看下圖:
提示:其組成是起始端點+控制點1+控制點2+終止端點
如下方法就是畫三次貝塞爾曲線的關鍵方法,以三個點畫一段曲線,一般和-moveToPoint:配合使用。
-(void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
看下效果圖:
實現程式碼是這樣的:
-(void)drawThirdBezierPath{
UIBezierPath*path=[UIBezierPathbezierPath];
// 設定起始端點
[pathmoveToPoint:CGPointMake(20,150)];
[pathaddCurveToPoint:CGPointMake(300,150)
controlPoint1:CGPointMake(160,0)
controlPoint2:CGPointMake(160,250)];
path.lineCapStyle=kCGLineCapRound;
path.lineJoinStyle=kCGLineJoinRound;
path.lineWidth=5.0;
UIColor*strokeColor=[UIColorredColor];
[strokeColorset];
[pathstroke];
}
我們需要注意,這裡確定的起始端點為(20,150),終止端點為(300, 150),基水平方向是一致的。控制點1的座標是(160,0),水平方向相當於在中間附近,這個引數可以調整。控制點2的座標是(160,250),如果以兩個端點的連線為水平線,那麼就是250-150=100,也就是在水平線下100。這樣看起來就像一個sin函式了。
原始碼下載
小夥伴們可以到github下載:UIBezierPathLayerDemos
版權宣告:本文為【標哥的技術部落格】原創出品,歡迎轉載,轉載時請註明出處!
相關文章
- 題庫精講(轉載)
- Synchronized 精講synchronized
- UIBezierPathUI
- Mysql 索引精講MySql索引
- Linux精講——磁碟掛載mount/解除安裝umountLinux
- Vue —— VueX精講(1)Vue
- Vue —— 精講 VueRouter(1)Vue
- 精講Redis:持久化Redis持久化
- Java設計模式精講Java設計模式
- Flutter動畫之粒子精講Flutter動畫
- React高階元件精講React元件
- 微信小程式——UI精講微信小程式UI
- 圖演算法精講演算法
- Linux精講——find命令Linux
- Linux精講——usermod命令Linux
- Linux精講——sudo命令Linux
- Linux精講——df命令Linux
- Linux精講——du命令Linux
- 聽蘋果之父講三個故事(轉載)蘋果
- 精講RestTemplate第6篇-檔案上傳下載與大檔案流式下載REST
- 精講響應式WebClient第4篇-檔案上傳與下載Webclient
- 精講Redis記憶體模型Redis記憶體模型
- 【機器學習】機器學習面試乾貨精講機器學習面試
- 微信小程式開發精講微信小程式
- 精講Python中的requests方法Python
- 分散式之 Redis 複習精講分散式Redis
- Mvvm 前端資料流框架精講MVVM前端框架
- Python正規表示式精講Python
- Linux精講——vim編輯器Linux
- Linux精講——修改密碼passwdLinux密碼
- Linux精講——fdisk磁碟分割槽Linux
- Linux精講——分割槽表fstabLinux
- Django模型中的save方法 精講Django模型
- 方法精講-言語1筆記筆記
- UIBezierPath貝塞爾曲線UI
- UIBezierPath的使用方法UI
- 《Java核心技術面試精講》27講學習總結Java面試
- 轉載:JAVA企業面試題精選 OOP 1-10Java面試題OOP