UIBezierPath簡(jiǎn)單使用

UIBezierPath

UIBezierPath是 UIKit 中的一個(gè)類,繼承于NSObject,是Core Graphics框架關(guān)于path的一個(gè)封裝。主要用于定義一個(gè)由直線/曲線組合而成的路徑, 并且可以在自定義視圖中渲染該路徑. 在使用的過程中, 我們只需要先指定好路徑的結(jié)構(gòu), 可以是直線呼寸、曲線退个、各種形狀, 然后使用系統(tǒng)為我們提供的方法將構(gòu)建好的路徑渲染出來即可提澎。

使用步驟

  1. 自定義視圖,重寫View的drawRect方法( 或者使用view添加CAShapeLayer
  2. 初始化創(chuàng)建UIBezierPath的對(duì)象
  3. 設(shè)置起始點(diǎn),繪制path路徑
  4. 設(shè)置UIBezierPath對(duì)象相關(guān)屬性 (比如lineWidth歇父、lineJoinStyle、aPath.lineCapStyle再愈、color)
  5. 使用stroke(線)或者 fill(填充)方法結(jié)束繪圖

初始化方法

直接就可以在初始化的時(shí)候,利用封裝好的方法確定路徑

+ (instancetype)bezierPath
//矩形路徑
+ (instancetype)bezierPathWithRect:(CGRect)rect
//矩形內(nèi)切橢圓路徑
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect
//圓角矩形
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius
//以"圓弧路徑"初始化一個(gè)UIBezierPath對(duì)象
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise

使用以上的初始化方法榜苫,即可繪制部分圖形(矩形、圓弧等)

繪制屬性和方法

繪制方法
利用當(dāng)前設(shè)置的屬性填充路徑的封閉范圍

- (void)fill
- (void)fillWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha

利用當(dāng)前設(shè)置的屬性根據(jù)路徑繪制圖形

- (void)stroke
- (void)strokeWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha

顏色設(shè)置

//[[UIColor blackColor] setFill];
- (void)setFill
//[[UIColor blackColor] setStroke];
- (void)setStroke

繪制屬性

//路徑寬度
@property(nonatomic) CGFloat lineWidth
//路徑的終點(diǎn)形狀翎冲,該屬性適用于開放路徑的起點(diǎn)和終點(diǎn)
@property(nonatomic) CGLineCap lineCapStyle
//路徑的連接點(diǎn)形狀, 默認(rèn)為kCGLineJoinMiter(全部連接), 其他可選項(xiàng)為kCGLineJoinRound(圓形連接)和kCGLineJoinBevel(斜角連接)
@property(nonatomic) CGLineJoin lineJoinStyle

路徑設(shè)置

//封閉曲線 連接起始點(diǎn)和結(jié)束點(diǎn)
- (void)closePath
//添加另一個(gè)路徑
- (void)appendPath:(UIBezierPath *)bezierPath;
//判斷是否包含某個(gè)點(diǎn)
- (BOOL)containsPoint:(CGPoint)point;

路徑繪制

使用CGContext畫圓

使用沒有封裝的Core Graphic繪圖

//一個(gè)不透明的Quartz 2D繪畫環(huán)境垂睬,相當(dāng)于一個(gè)畫布
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);//畫筆的顏色
CGContextSetLineWidth(context, 1.0);//線寬
CGContextAddArc(context,
                100, 20, 15, 0, M_PI * 2.0, 0);//添加圓
CGContextDrawPath(context, kCGPathStroke);//繪制路徑

使用UIBezierPat初始化方法繪制圓弧

UIBezierPath就是針對(duì)Core Graphics庫中的CGPathRef的封裝,降低繪圖的難度

- (void)drawRect:(CGRect)rect
{
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(rect.size.width / 2, rect.size.height /2) radius:rect.size.width/2.0 startAngle:0 endAngle:2*M_PI clockwise:YES];;
    [path stroke];
    //    [path fill];
}
基本圖形

使用點(diǎn)構(gòu)造路徑

設(shè)置初始點(diǎn)

- (void)moveToPoint:(CGPoint)point

增加一個(gè)點(diǎn)構(gòu)成一條線的路徑

- (void)addLineToPoint:(CGPoint)point

添加弧線的路線

- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise

繪制三角形

- (void)drawRect:(CGRect)rect {

    UIBezierPath *path = [[UIBezierPath alloc] init];
    //path移動(dòng)到開始畫圖的位置
    [path moveToPoint:CGPointMake(rect.origin.x, rect.origin.y)];
    [path addLineToPoint:CGPointMake(rect.origin.x + rect.size.width, rect.origin.y)];
    [path addLineToPoint:CGPointMake(rect.origin.x + rect.size.width/2, rect.origin.y + rect.size.height)];
    //關(guān)閉path
    [path closePath];
    [path fill];
}

使用UIBezierPath與CALayer配合使用,不需重寫drawRect方法

CAShapeLayer *layer = [CAShapeLayer layer];
layer.frame = CGRectMake(100, 400, 200, 200);
layer.lineWidth = 3.0f;
layer.strokeColor = [UIColor orangeColor].CGColor;
layer.fillColor = [UIColor yellowColor].CGColor;
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(50, 100)];
[path addLineToPoint:CGPointMake(150, 100)];
[path addLineToPoint:CGPointMake(100, 50)];
[path stroke];
[path closePath];
layer.path = path.CGPath;
[view.layer addSublayer:layer];

繪制五角星

UIBezierPath *path2 = [UIBezierPath bezierPath];
    [path2 moveToPoint:CGPointMake(100, 400)];
    [path2 addLineToPoint:CGPointMake(300, 400)];
    [path2 addLineToPoint:CGPointMake(150, 550)];
    [path2 addLineToPoint:CGPointMake(200, 300)];
    [path2 addLineToPoint:CGPointMake(250, 550)];
    [path2 closePath];
//    path2.lineWidth = 10;
//    [path2 stroke];
    [[UIColor redColor] setFill];
    [path2 fill];

二階羔飞、三階貝塞爾曲線

底下有控制點(diǎn)算法的文章肺樟,有興趣可以研究下

二階貝塞爾曲線

// endPoint: 曲線的終點(diǎn)位置
// controlPoint: 控制點(diǎn)
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint

繪制二階曲線
二階動(dòng)畫
- (void)drawRect:(CGRect)rect
{
    UIBezierPath *path = [UIBezierPath bezierPath];
    CGPoint currentPoint = CGPointMake(100, rect.size.height / 2.0);
    CGPoint endPoint = CGPointMake(300, rect.size.height / 2.0);
    [path moveToPoint:currentPoint];
    
    if (_touchPoint.y == 0) {
        _touchPoint.x = 200;
        _touchPoint.y = rect.size.height / 2.0 - 100;
    }
    [path addQuadCurveToPoint:endPoint controlPoint:_touchPoint];
    [path stroke];
    
    //起始點(diǎn)
    UIBezierPath *dot1 = [UIBezierPath bezierPathWithArcCenter:currentPoint radius:2 startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [dot1 fill];
    //結(jié)束點(diǎn)
    UIBezierPath *dot2 = [UIBezierPath bezierPathWithArcCenter:endPoint radius:2 startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [dot2 fill];
    //控制點(diǎn)
    UIBezierPath *dot3 = [UIBezierPath bezierPathWithArcCenter:_touchPoint radius:2 startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [[UIColor redColor] setFill];
    [dot3 fill];
    //控制線點(diǎn)
    UIBezierPath *path2 = [UIBezierPath bezierPath];
    CGFloat dashPattern[] = {3,1};// 3實(shí)線,1空白
    [path2 setLineDash:dashPattern count:1 phase:1];
    [path2 moveToPoint:currentPoint];
    [path2 addLineToPoint:_touchPoint];
    [path2 addLineToPoint:endPoint];
    [path2 stroke];
}

三階貝塞爾曲線

// endPoint: 曲線的終點(diǎn)位置
// controlPoint1: 第一控制點(diǎn)
// controlPoint2: 第二控制點(diǎn)
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
繪制三階貝塞爾曲線
三階動(dòng)畫
- (void)drawRect:(CGRect)rect
{
    UIBezierPath *path = [UIBezierPath bezierPath];
    CGPoint currentPoint = CGPointMake(10, rect.size.height / 2.0);
    CGPoint endPoint = CGPointMake(300, rect.size.height / 2.0);
    [path moveToPoint:currentPoint];
    
    if (_controlPoint1.y == 0) {
        _controlPoint1.x = 100;
        _controlPoint1.y = rect.size.height / 2.0 - 100;
    }
    if (_controlPoint2.y == 0) {
        _controlPoint2.x = 200;
        _controlPoint2.y = rect.size.height / 2.0 + 100;
    }
//    [path addQuadCurveToPoint:endPoint controlPoint:_touchPoint];
    [path addCurveToPoint:endPoint controlPoint1:_controlPoint1 controlPoint2:_controlPoint2];
    [path stroke];
    
    //起始點(diǎn)
    UIBezierPath *dot1 = [UIBezierPath bezierPathWithArcCenter:currentPoint radius:2 startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [dot1 fill];
    //結(jié)束點(diǎn)
    UIBezierPath *dot2 = [UIBezierPath bezierPathWithArcCenter:endPoint radius:2 startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [dot2 fill];
    //控制點(diǎn)1
    UIBezierPath *dot3 = [UIBezierPath bezierPathWithArcCenter:_controlPoint1 radius:2 startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [[UIColor redColor] setFill];
    [dot3 fill];
    //控制點(diǎn)2
    UIBezierPath *dot4 = [UIBezierPath bezierPathWithArcCenter:_controlPoint2 radius:2 startAngle:0 endAngle:2 * M_PI clockwise:YES];
    [[UIColor redColor] setFill];
    [dot4 fill];

    //控制線點(diǎn)
    UIBezierPath *path2 = [UIBezierPath bezierPath];
    CGFloat dashPattern[] = {3,1};// 3實(shí)線逻淌,1空白
    [path2 setLineDash:dashPattern count:1 phase:1];
    [path2 moveToPoint:currentPoint];
    [path2 addLineToPoint:_controlPoint1];
    [path2 addLineToPoint:_controlPoint2];
    [path2 addLineToPoint:endPoint];
    [path2 stroke];
}

Demo地址

貝塞爾曲線

參考文章

貝塞爾曲線控制點(diǎn)算法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末么伯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子卡儒,更是在濱河造成了極大的恐慌田柔,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骨望,死亡現(xiàn)場(chǎng)離奇詭異硬爆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)擎鸠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門缀磕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人劣光,你說我怎么就攤上這事袜蚕。” “怎么了绢涡?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵牲剃,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我雄可,道長(zhǎng)凿傅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任数苫,我火速辦了婚禮聪舒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘文判。我一直安慰自己过椎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布戏仓。 她就那樣靜靜地躺著疚宇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赏殃。 梳的紋絲不亂的頭發(fā)上敷待,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音仁热,去河邊找鬼榜揖。 笑死勾哩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的举哟。 我是一名探鬼主播思劳,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼妨猩!你這毒婦竟也來了潜叛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤壶硅,失蹤者是張志新(化名)和其女友劉穎威兜,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庐椒,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡椒舵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了约谈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笔宿。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖棱诱,靈堂內(nèi)的尸體忽然破棺而出措伐,到底是詐尸還是另有隱情,我是刑警寧澤军俊,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站捧存,受9級(jí)特大地震影響粪躬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜昔穴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一镰官、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吗货,春花似錦泳唠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至勇垛,卻和暖如春脖母,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闲孤。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工谆级, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓肥照,卻偏偏與公主長(zhǎng)得像脚仔,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子舆绎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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