UIBezierPath

1.使用UIBezierPath畫圖步驟

創(chuàng)建一個UIBezierPath對象

調(diào)用-moveToPoint:設(shè)置初始線段的起點

添加線或者曲線去定義一個或者多個子路徑

改變UIBezierPath對象跟繪圖相關(guān)的屬性。如,我們可以設(shè)置畫筆的屬性、填充樣式等


2.工廠方法

+ (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;

這個使用比較多,因為這個工廠方法創(chuàng)建的對象,我們可以根據(jù)我們的需要任意定制樣式,可以畫任何我們想畫的圖形。

+ (instancetype)bezierPathWithRect:(CGRect)rect;

這個工廠方法根據(jù)一個矩形畫貝塞爾曲線。

+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;

這個工廠方法根據(jù)一個矩形畫內(nèi)切曲線。通常用它來畫圓或者橢圓。

+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect

cornerRadius:(CGFloat)cornerRadius;+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect

byRoundingCorners:(UIRectCorner)corners

cornerRadii:(CGSize)cornerRadii;

第一個工廠方法是畫矩形,但是這個矩形是可以畫圓角的。第一個參數(shù)是矩形,第二個參數(shù)是圓角大小。

第二個工廠方法功能是一樣的,但是可以指定某一個角畫成圓角。像這種我們就可以很容易地給UIView擴展添加圓角的方法了。

+ (instancetype)bezierPathWithArcCenter:(CGPoint)center? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? radius:(CGFloat)radius? ? ? ? ? ? ? ? ? ? ? ? ? ? ? startAngle:(CGFloat)startAngle? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? endAngle:(CGFloat)endAngle? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clockwise:(BOOL)clockwise;

這個工廠方法用于畫弧,參數(shù)說明如下:

center: 弧線中心點的坐標(biāo)

radius: 弧線所在圓的半徑

startAngle: 弧線開始的角度值

endAngle: 弧線結(jié)束的角度值

clockwise: 是否順時針畫弧線

溫馨提示:我們下面的代碼都是在自定義的BezierPathView類中的- (void)drawRect:(CGRect)rect方法中調(diào)用

畫三角形

先看效果圖:

image

// 畫三角形- (void)drawTrianglePath {UIBezierPath*path = [UIBezierPathbezierPath];? [path moveToPoint:CGPointMake(20,20)];? [path addLineToPoint:CGPointMake(self.frame.size.width-40,20)];? [path addLineToPoint:CGPointMake(self.frame.size.width/2,self.frame.size.height-20)];// 最后的閉合線是可以通過調(diào)用closePath方法來自動生成的,也可以調(diào)用-addLineToPoint:方法來添加//? [path addLineToPoint:CGPointMake(20, 20)];[path closePath];// 設(shè)置線寬path.lineWidth=1.5;// 設(shè)置填充顏色UIColor*fillColor = [UIColorgreenColor];? [fillColor set];? [path fill];// 設(shè)置畫筆顏色UIColor*strokeColor = [UIColorblueColor];? [strokeColor set];// 根據(jù)我們設(shè)置的各個點連線[path stroke];}

我們設(shè)置畫筆顏色通過set方法:

UIColor*strokeColor = [UIColorblueColor];[strokeColor set];

如果我們需要設(shè)置填充顏色,比如這里設(shè)置為綠色,那么我們需要在設(shè)置畫筆顏色之前先設(shè)置填充顏色,否則畫筆顏色就被填充顏色替代了。也就是說,如果要讓填充顏色與畫筆顏色不一樣,那么我們的順序必須是先設(shè)置填充顏色再設(shè)置畫筆顏色。如下,這兩者順序不能改變。因為我們設(shè)置填充顏色也是跟設(shè)置畫筆顏色一樣調(diào)用UIColor的-set方法。

// 設(shè)置填充顏色UIColor*fillColor = [UIColorgreenColor];[fillColor set];[path fill];// 設(shè)置畫筆顏色UIColor*strokeColor = [UIColorblueColor];[strokeColor set];

畫矩形

先看效果圖:

image

// 畫矩形- (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;// 設(shè)置填充顏色UIColor*fillColor = [UIColorgreenColor];? [fillColor set];? [path fill];// 設(shè)置畫筆顏色UIColor*strokeColor = [UIColorblueColor];? [strokeColor set];// 根據(jù)我們設(shè)置的各個點連線[path stroke];}

lineCapStyle屬性是用來設(shè)置線條拐角帽的樣式的,其中有三個選擇:

/* Line cap styles. */typedefCF_ENUM(int32_t,CGLineCap) {? ? kCGLineCapButt,? ? kCGLineCapRound,? ? kCGLineCapSquare};

其中,第一個是默認的,第二個是輕微圓角,第三個正方形。

lineJoinStyle屬性是用來設(shè)置兩條線連結(jié)點的樣式,其中也有三個選擇:

/* Line join styles. */typedefCF_ENUM(int32_t,CGLineJoin) {? ? kCGLineJoinMiter,? ? kCGLineJoinRound,? ? kCGLineJoinBevel};

其中,第一個是默認的表示斜接,第二個是圓滑銜接,第三個是斜角連接。

畫圓

我們可以使用+ bezierPathWithOvalInRect:方法來畫圓,當(dāng)我們傳的rect參數(shù)是一下正方形時,畫出來的就是圓。

先看效果圖:

image

- (void)drawCiclePath {// 傳的是正方形,因此就可以繪制出圓了UIBezierPath*path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(20,20,self.frame.size.width-40,self.frame.size.width-40)];// 設(shè)置填充顏色UIColor*fillColor = [UIColorgreenColor];? [fillColor set];? [path fill];// 設(shè)置畫筆顏色UIColor*strokeColor = [UIColorblueColor];? [strokeColor set];// 根據(jù)我們設(shè)置的各個點連線[path stroke];}

注意:要畫圓,我們需要傳的rect參數(shù)必須是正方形哦!

畫橢圓

先看效果圖:

image

前面我們已經(jīng)畫圓了,我們可以使用+ bezierPathWithOvalInRect:方法來畫圓,當(dāng)我們傳的rect參數(shù)是一下正方形時,畫出來的就是圓。那么我們要是不傳正方形,那么繪制出來的就是橢圓了。

// 畫橢圓- (void)drawOvalPath {// 傳的是不是正方形,因此就可以繪制出橢圓圓了UIBezierPath*path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(20,20,self.frame.size.width-80,self.frame.size.height-40)];// 設(shè)置填充顏色UIColor*fillColor = [UIColorgreenColor];? [fillColor set];? [path fill];// 設(shè)置畫筆顏色UIColor*strokeColor = [UIColorblueColor];? [strokeColor set];// 根據(jù)我們設(shè)置的各個點連線[path stroke];}

畫帶圓角的矩形

+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect

cornerRadius:(CGFloat)cornerRadius;+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect

byRoundingCorners:(UIRectCorner)corners

cornerRadii:(CGSize)cornerRadii;

第一個工廠方法是畫矩形,但是這個矩形是可以畫圓角的。第一個參數(shù)是矩形,第二個參數(shù)是圓角大小。

第二個工廠方法功能是一樣的,但是可以指定某一個角畫成圓角。像這種我們就可以很容易地給UIView擴展添加圓角的方法了。

四個都是圓角10:

image

- (void)drawRoundedRectPath {UIBezierPath*path = [UIBezierPathbezierPathWithRoundedRect:CGRectMake(20,20,self.frame.size.width-40,self.frame.size.height-40) cornerRadius:10];// 設(shè)置填充顏色UIColor*fillColor = [UIColorgreenColor];? [fillColor set];? [path fill];// 設(shè)置畫筆顏色UIColor*strokeColor = [UIColorblueColor];? [strokeColor set];// 根據(jù)我們設(shè)置的各個點連線[path stroke];}

如果要畫只有一個角是圓角,那么我們就修改創(chuàng)建方法:

UIBezierPath*path = [UIBezierPathbezierPathWithRoundedRect:CGRectMake(20,20,self.frame.size.width-40,self.frame.size.height-40) byRoundingCorners:UIRectCornerTopRightcornerRadii:CGSizeMake(20,20)];

其中第一個參數(shù)一樣是傳了個矩形,第二個參數(shù)是指定在哪個方向畫圓角,第三個參數(shù)是一個CGSize類型,用來指定水平和垂直方向的半徑的大小。看下效果圖:

image

畫弧

畫弧前,我們需要了解其參考系,如下圖(圖片來自網(wǎng)絡(luò)):

image

#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:100startAngle:0endAngle:kDegreesToRadians(135)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clockwise:YES];? path.lineCapStyle= kCGLineCapRound;? path.lineJoinStyle= kCGLineJoinRound;? path.lineWidth=5.0;UIColor*strokeColor = [UIColorredColor];? [strokeColor set];? [path stroke];}

效果圖如下:

image

我們要明確一點,畫弧參數(shù)startAngle和endAngle使用的是弧度,而不是角度,因此我們需要將常用的角度轉(zhuǎn)換成弧度。對于效果圖中,我們設(shè)置弧的中心為控件的中心,起點弧度為0,也就是正東方向,而終點是135度角的位置。如果設(shè)置的clockwise:YES是逆時針方向繪制,如果設(shè)置為NO,效果如下:

image

這兩者正好是相反的。

畫二次貝塞爾曲線

先來學(xué)習(xí)一下關(guān)于控制點,如下圖(圖片來自網(wǎng)絡(luò)):

image

畫二次貝塞爾曲線,是通過調(diào)用此方法來實現(xiàn)的:

- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint

參數(shù)說明:

endPoint:終端點

controlPoint:控制點,對于二次貝塞爾曲線,只有一個控制點

看效果圖:

image

- (void)drawSecondBezierPath {UIBezierPath*path = [UIBezierPathbezierPath];// 首先設(shè)置一個起始點[path moveToPoint:CGPointMake(20,self.frame.size.height-100)];// 添加二次曲線[path addQuadCurveToPoint: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];? [strokeColor set];? [path stroke];}

畫二次貝塞爾曲線的步驟:

先設(shè)置一個起始點,也就是通過-moveToPoint:設(shè)置

調(diào)用-addQuadCurveToPoint:controlPoint:方法設(shè)置終端點和控制點,以畫二次曲線

在效果圖中,拱橋左邊的起始點就是我們設(shè)置的起始點,最右邊的終點,就是我們設(shè)置的終端點,而我們設(shè)置的控制點為(width / 2, 0)對應(yīng)于紅色矩形中水平方向在正中央,而垂直方向在最頂部。

這個樣式看起來很像sin或者cos函數(shù)吧?這兩個只是特例而已,其實可以畫任意圖形,只是想不到,沒有做不到的。

畫三次貝塞爾曲線

貝塞爾曲線必定通過首尾兩個點,稱為端點;中間兩個點雖然未必要通過,但卻起到牽制曲線形狀路徑的作用,稱作控制點。關(guān)于三次貝塞爾曲線的控制器,看下圖:

image

提示:其組成是起始端點+控制點1+控制點2+終止端點

如下方法就是畫三次貝塞爾曲線的關(guān)鍵方法,以三個點畫一段曲線,一般和-moveToPoint:配合使用。

- (void)addCurveToPoint:(CGPoint)endPoint? ? ? ? ? controlPoint1:(CGPoint)controlPoint1? ? ? ? ? controlPoint2:(CGPoint)controlPoint2

看下效果圖:

image

實現(xiàn)代碼是這樣的:

- (void)drawThirdBezierPath {UIBezierPath*path = [UIBezierPathbezierPath];// 設(shè)置起始端點[path moveToPoint:CGPointMake(20,150)];? [path addCurveToPoint:CGPointMake(300,150)? ? ? ? ? controlPoint1:CGPointMake(160,0)? ? ? ? ? controlPoint2:CGPointMake(160,250)];? path.lineCapStyle= kCGLineCapRound;? path.lineJoinStyle= kCGLineJoinRound;? path.lineWidth=5.0;UIColor*strokeColor = [UIColorredColor];? [strokeColor set];? [path stroke];}

我們需要注意,這里確定的起始端點為(20,150),終止端點為(300, 150),基水平方向是一致的。控制點1的坐標(biāo)是(160,0),水平方向相當(dāng)于在中間附近,這個參數(shù)可以調(diào)整。控制點2的坐標(biāo)是(160,250),如果以兩個端點的連線為水平線,那么就是250-150=100,也就是在水平線下100。這樣看起來就像一個sin函數(shù)了。

文/標(biāo)哥的技術(shù)博客(簡書作者)

原文鏈接:http://www.lxweimin.com/p/734b34e82135

著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),并標(biāo)注“簡書作者”。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內(nèi)容