iOS 繪圖-UIBezierPath

UIBezierPath主要用來繪制矢量圖形,它是基于Core Graphics對CGPathRef數(shù)據(jù)類型和path繪圖屬性的一個封裝焚鲜。使用UIBezierPath可以定義簡單的形狀垦页。


1雀费、UIBezierPath的屬性

1. CGPath:將UIBezierPath類轉(zhuǎn)換成CGPath,類似于UIColor的CGColor
2. currentPoint:當(dāng)前path的位置痊焊,可以理解為path的終點
3. lineWidth:path寬度
4. lineCapStyle:path端點樣式枚舉盏袄,有3種樣式
    kCGLineCapButt,     // 無端點      
    kCGLineCapRound,    // 圓形端點  
    kCGLineCapSquare    // 方形端點(樣式上和kCGLineCapButt是一樣的忿峻,但是比kCGLineCapButt長一點)
5.  lineJoinStyle:拐角樣式枚舉,有3種樣式
    kCGLineJoinMiter,    // 尖角
    kCGLineJoinRound,    // 圓角
    kCGLineJoinBevel     // 缺角
6.miterLimit:最大斜接長度(只有在使用kCGLineJoinMiter是才有效)辕羽,邊角的角度越小逛尚,斜接長度就會越大
  為了避免斜接長度過長,使用lineLimit屬性限制
  如果斜接長度超過miterLimit刁愿,邊角就會以KCALineJoinBevel類型來顯示


2绰寞、UIBezierPath與Quartz2D

即UIBezierPath在drawRect中的使用,在實際中铣口,我們多使用UIBezierPath來自定義視圖滤钱。

矩形
- (void)drawRect:(CGRect)rect {
   
    CGFloat lineWidth = 3;
    
    //矩形(第一種方式)
    UIBezierPath *rectPath = [UIBezierPath bezierPathWithRect:CGRectMake(10, 10, 50,50 )];
    rectPath.lineWidth = lineWidth*2;
    rectPath.lineCapStyle = kCGLineCapRound;
    rectPath.lineJoinStyle = kCGLineJoinRound;
    //閉合路徑
    [rectPath closePath];
    [[UIColor greenColor] set];
    //繪制邊緣
    [rectPath stroke];
    
    //矩形(第二種方式)
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    UIBezierPath *pathRect = [UIBezierPath bezierPathWithRect:CGRectMake(70, 10, 50,50 )];
    CGContextAddPath(ctx, pathRect.CGPath);
    [[UIColor purpleColor] set];
    CGContextFillPath(ctx);

}
圓/弧
- (void)drawRect:(CGRect)rect {
   
    CGFloat lineWidth = 3;
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //矩形圓
    UIBezierPath *roundPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(130, 10, 50, 50) cornerRadius:10];
    CGContextAddPath(ctx, roundPath.CGPath);
    CGContextSetLineWidth(ctx, lineWidth);
    [[UIColor orangeColor] set];
    CGContextStrokePath(ctx);
    
    //實心圓
    UIBezierPath *arcPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(35, 95) radius:25 startAngle:0 endAngle:M_PI*2 clockwise:NO];
    [arcPath addLineToPoint:CGPointMake(35, 95)];
    [arcPath closePath];
    [[UIColor brownColor] set];
    [arcPath fill];
    CGContextSetRGBStrokeColor(ctx, 1, 0, 0, 1);
    //空心圓
    /*
     *  clockwise 1為順時針  0為逆時針
     *  順時針的理解:指定1創(chuàng)建順時針弧或0創(chuàng)建逆時針弧(startAngle為0時為逆時針弧脑题,非0為順時針患住)
     */
    UIBezierPath *arcKPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(155, 95) radius:25 startAngle:M_PI_2 endAngle:M_PI clockwise:NO];
    CGContextAddPath(ctx, arcKPath.CGPath);
    CGContextSetLineWidth(ctx, lineWidth);
    [[UIColor lightGrayColor] set];
    CGContextStrokePath(ctx);
    
    float angle = 0;
    CGPoint center = CGPointMake(150, 160);
    for (int index = 1; index < 5; index++) {
        
        CGFloat startAngle = angle;
        CGFloat endAngle = index*M_PI_2;
        //實心圓
        UIBezierPath *arcPath = [UIBezierPath bezierPathWithArcCenter:center radius:30 startAngle:startAngle endAngle:endAngle clockwise:YES];
        [arcPath addLineToPoint:center];
        [arcPath closePath];
        [[self randColor] set];
        [arcPath fill];
        
        angle = endAngle;
    }
    
}

- (UIColor *)randColor
{
    //rand(),就返回一個類型為int的整數(shù),其范圍是0到RAND_MAX
    float red = rand() / (float)RAND_MAX;
    float green = rand() / (float)RAND_MAX;
    float blue = rand() / (float)RAND_MAX;
    
    return [UIColor colorWithRed:red green:green blue:blue alpha:1];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self setNeedsDisplay];
}

線條
- (void)drawRect:(CGRect)rect {
   
    CGFloat lineWidth = 3;
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //線條
    UIBezierPath *linePath = [UIBezierPath bezierPath];
    [linePath moveToPoint:CGPointMake(10, 130)];
    [linePath addLineToPoint:CGPointMake(60, 190)];
    [linePath moveToPoint:CGPointMake(60, 130)];
    [linePath addLineToPoint:CGPointMake(10, 190)];
    CGContextAddPath(ctx, linePath.CGPath);
    CGContextSetLineWidth(ctx, lineWidth*3);
    CGContextSetLineCap(ctx, kCGLineCapSquare);
    CGContextSetLineJoin(ctx, kCGLineJoinBevel);
    [[UIColor blackColor] set];
    CGContextStrokePath(ctx);
}

效果

UIBezierPath.png
曲線
塞爾曲線原理.png
- (void)drawRect:(CGRect)rect {
    
    //1.獲取跟View相關(guān)聯(lián)的上下文.】
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //2.描述路徑
    UIBezierPath *path = [UIBezierPath  bezierPath];
    //畫曲線,設(shè)置起點.還有一個控制點(用來控制曲線的方向跟彎曲程度)
    //設(shè)置起點
    //A: CGPointMake(10, 150)
    [path moveToPoint:CGPointMake(10, 150)];
    //添加一要曲線到某個點
    //C:CGPointMake(200, 150)    B:CGPointMake(150, 10)
    [path addQuadCurveToPoint:CGPointMake(200, 150) controlPoint:CGPointMake(150, 10)];
    //3.把路徑添加到上下文當(dāng)中
    CGContextAddPath(ctx, path.CGPath);
    //4.把上下文的內(nèi)容渲染View上
    CGContextStrokePath(ctx);
    
}

2旭蠕、UIBezierPath與CAShapeLayer

UIBezierPath與CAShapeLayer的結(jié)合停团,是我們開發(fā)中最常見的,功能很強(qiáng)大掏熬。

CAShapeLayer與UIBezierPath的關(guān)系

CAShapeLayer中shape代表形狀的意思佑稠,所以需要形狀才能生效
貝塞爾曲線可以創(chuàng)建基于矢量的路徑,而UIBezierPath類是對CGPathRef的封裝
貝塞爾曲線給CAShapeLayer提供路徑旗芬,CAShapeLayer在提供的路徑中進(jìn)行渲染舌胶。路徑會閉環(huán),所以繪制出了Shape
用于CAShapeLayer的貝塞爾曲線作為path疮丛,其path是一個首尾相接的閉環(huán)的曲線幔嫂,即使該貝塞爾曲線不是一個閉環(huán)的曲線

例如設(shè)置圓角:

- (void)setFillet
{
    UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
    imageView.image = [UIImage imageNamed:@"test"];
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:imageView.bounds.size];

    CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
    //設(shè)置大小
    maskLayer.frame = imageView.bounds;
    //設(shè)置圖形樣子
    maskLayer.path = maskPath.CGPath;
    imageView.layer.mask = maskLayer;
}

自定義視圖

- (void)addCustomizeView
{
    CGFloat H = self.view.frame.size.height;
    CGFloat W = self.view.frame.size.width;
    CGFloat layerHeight = self.view.frame.size.height * 0.1;
    
    UIBezierPath *bezier = [UIBezierPath bezierPath];
    [bezier moveToPoint:CGPointMake(0, H-layerHeight)];
    [bezier addLineToPoint:(CGPointMake(0, H - 1))];
    [bezier addLineToPoint:(CGPointMake(W, H - 1))];
    [bezier addLineToPoint:CGPointMake(W, H-layerHeight)];
    [bezier addQuadCurveToPoint:CGPointMake(0, H-layerHeight) controlPoint:CGPointMake(W/2, H-layerHeight-40)];
    
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.lineWidth = 3;
    shapeLayer.path = bezier.CGPath;
    shapeLayer.fillColor = [UIColor grayColor].CGColor;
    shapeLayer.strokeColor = [UIColor greenColor].CGColor;
    [self.view.layer addSublayer:shapeLayer];
 }

效果

customizeView.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市誊薄,隨后出現(xiàn)的幾起案子履恩,更是在濱河造成了極大的恐慌,老刑警劉巖呢蔫,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件切心,死亡現(xiàn)場離奇詭異,居然都是意外死亡片吊,警方通過查閱死者的電腦和手機(jī)绽昏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俏脊,“玉大人全谤,你說我怎么就攤上這事∫叮” “怎么了认然?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵补憾,是天一觀的道長。 經(jīng)常有香客問我卷员,道長余蟹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任子刮,我火速辦了婚禮威酒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘挺峡。我一直安慰自己葵孤,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布橱赠。 她就那樣靜靜地躺著尤仍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狭姨。 梳的紋絲不亂的頭發(fā)上宰啦,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機(jī)與錄音饼拍,去河邊找鬼赡模。 笑死,一個胖子當(dāng)著我的面吹牛师抄,可吹牛的內(nèi)容都是我干的漓柑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼叨吮,長吁一口氣:“原來是場噩夢啊……” “哼辆布!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起茶鉴,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤锋玲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涵叮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惭蹂,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年围肥,在試婚紗的時候發(fā)現(xiàn)自己被綠了剿干。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜂怎。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡穆刻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出杠步,到底是詐尸還是另有隱情氢伟,我是刑警寧澤榜轿,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站朵锣,受9級特大地震影響谬盐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜诚些,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一飞傀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诬烹,春花似錦砸烦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至家破,卻和暖如春颜说,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汰聋。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工门粪, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烹困。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓庄拇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親韭邓。 傳聞我的和親對象是個殘疾皇子措近,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

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