iOS CAShapeLayer & UIBezierPath畫線、畫圖


CAShapeLayer 繼承與CALayer( 主要用於設置圖層的形狀)

CAShapeLayer對象屬性列表

屬性名 描述
path CGPathRef 對象,圖形邊線路徑
lineWidth 邊線的寬度
strokeColor 邊線的顏色
lineDashPattern 設置邊線的樣式,默認為實線,該數組為一個NSNumber數組,數組中的數值依次表示虛線中,單個線的長度,和空白的長度,如:數組@[2,2,3,4] 表示 有長度為2的線,長度為2的空白,長度為3的線,長度為4的空白 不斷循環后組成的虛線。如圖:lineDashPatttern
lineDashPhase 邊線樣式的起始位置,即,如果lineDashPattern設置為@[2,2,3,4],lineDashPhase即為第一個長度為2的線的起始位置
lineCap 線終點的樣式,默認 kCALineCapButt kCALineCapButt kCAlineCapRound kCAlineCapRound kCALineCapSquare kCALineCapSquare
lineJoin 線拐點處的樣式,默認 kCALineJoinMiter kCALineJoinMite kCALineJoinRound kCALineJoinRound kCALineJoinBevel kCALineJoinBeve
strokeStart strokeEnd CGFloat類型,[0,1] 表示畫邊線的起點和終點(即在路徑上的百分比)
fillColor CGColorRef對象,圖形填充色,默認為黑色

結合UIBezierPath 與 CAShapeLayer 畫圖

將UIBezierPath 對象 轉化為CGPathRef 對象, 賦值給CAShapeLayer的path屬性即可,即可畫出各種線條和圖形

layer.path = bezierPath.CGPath;

畫折線

  • 畫折線的UIBezierPath相關方法

+ (instancetype)bezierPath
生成一個UIBezierPath對象, 多用於畫 不規則曲線 或 多邊圖形
 
- (void)moveToPoint:(CGPoint)point
添加路徑起點
 
- (void)addLineToPoint:(CGPoint)point
添加路徑起點外的其他點

在矩形中畫一條折線

  • 效果圖
![折線](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122033402-1496487418.png)
  • 代碼
    // 需要畫線的視圖
    UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame)- 100, 200, 200)];
    lineView.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:lineView];
    
    // 線的路徑
    UIBezierPath *linePath = [UIBezierPath bezierPath];
    // 起點
    [linePath moveToPoint:CGPointMake(20, 20)];
    // 其他點
    [linePath addLineToPoint:CGPointMake(160, 160)];
    [linePath addLineToPoint:CGPointMake(180, 50)];
    
    CAShapeLayer *lineLayer = [CAShapeLayer layer];
    
    lineLayer.lineWidth = 2;
    lineLayer.strokeColor = [UIColor greenColor].CGColor;
    lineLayer.path = linePath.CGPath;
    lineLayer.fillColor = nil; // 默認為blackColor
    
    [lineView.layer addSublayer:lineLayer];
    

畫多邊形

  • UIBezierPath相關方法

- (void)closePath
封閉曲線(連接曲線的起點和終點形成封閉曲線)

在矩形視圖中畫一個三角形

  • 效果圖
![多邊形](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122033590-419945522.png)
  • 代碼:
    // 需要多邊形的視圖
    UIView * polygonView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
    polygonView.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:polygonView];
    
    // 線的路徑
    UIBezierPath *polygonPath = [UIBezierPath bezierPath];
    
    // 這些點的位置都是相對於所在視圖的
    // 起點
    [polygonPath moveToPoint:CGPointMake(20, 40)];
    // 其他點
    [polygonPath addLineToPoint:CGPointMake(160, 160)];
    [polygonPath addLineToPoint:CGPointMake(140, 50)];
    
    [polygonPath closePath]; // 添加一個結尾點和起點相同

    CAShapeLayer *polygonLayer = [CAShapeLayer layer];
    polygonLayer.lineWidth = 2;
    polygonLayer.strokeColor = [UIColor greenColor].CGColor;
    polygonLayer.path = polygonPath.CGPath;
    polygonLayer.fillColor = nil; // 默認為blackColor
    [polygonView.layer addSublayer:polygonLayer];
    

畫橢圓或圓

  • 畫橢圓或圓的UIBezierPath相關方法

+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect
生成一個矩形的內切橢圓UIBezierPath對象,如果矩形是正方形,就為內切圓

在矩形中畫內切橢圓

  • 效果圖
![矩形-內切橢圓](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122033652-1591637247.png)
  • 代碼
// 需要圓視圖
    UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 130, CGRectGetMidY(self.view.frame) - 100, 260, 200)];
    view.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:view];
    
    // 線的路徑
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:view.bounds];
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.lineWidth = 2;
    pathLayer.strokeColor = [UIColor greenColor].CGColor;
    pathLayer.path = path.CGPath;
    pathLayer.fillColor = nil; // 默認為blackColor
    [view.layer addSublayer:pathLayer];

在矩形中畫內切圓,並把正方形切為圓

  • 效果圖
![圓角-內切圓](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122033637-538903717.png)
  • 代碼
    UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
    view.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:view];
    
    // 線的路徑
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:view.bounds];
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.lineWidth = 2;
    pathLayer.strokeColor = [UIColor greenColor].CGColor;
    pathLayer.path = path.CGPath;
    // [view.layer addSublayer:pathLayer];
    // pathLayer.fillColor = nil; // 默認為blackColor
    view.layer.mask = pathLayer; // layer 的 mask屬性,添加蒙版

畫圓角矩形

  • 畫圓角矩形的UIBezierPath相關方法

+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius
生成一個自定義圓角大小的矩形UIBezierPath對象

矩形添加圓角,切為圓角矩形

  • 效果圖
![圓角矩形](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122033684-445218060.png)
  • 代碼
    // 需要畫圓角矩形
    UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
    view.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:view];
    
    // 線的路徑
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:view.bounds cornerRadius:50];
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.lineWidth = 2;
    pathLayer.strokeColor = [UIColor greenColor].CGColor;
    pathLayer.path = path.CGPath;
    // pathLayer.fillColor = [UIColor lightGrayColor].CGColor; // 默認為blackColor
    // [polygonView.layer addSublayer:polygonLayer];
    view.layer.mask = pathLayer; // layer 的 mask屬性,添加蒙版

畫單角的圓角矩形的UIBezierPath相關方法

+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii
為矩形的某一個角添加自定義大小的圓角(當自定義的圓角大小超過矩形寬或高的一半是,自動取矩形寬或高的一半作為圓角大小)

如果想對視圖單個角切圓角,和圓切圓角相同只需將UIBezierPath對象添加為mask即可。

給矩形左上角添加圓角:

  • 效果圖
![單角-圓角矩形](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122033699-1682402628.png)
  • 代碼
// 需要圓視圖
    UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
    view.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:view];
    
    // 線的路徑
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:UIRectCornerTopLeft cornerRadii:CGSizeMake(100, 0)];
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.lineWidth = 2;
    pathLayer.strokeColor = [UIColor greenColor].CGColor;
    pathLayer.fillColor = nil; // 默認為blackColor
    pathLayer.path = path.CGPath;
    [view.layer addSublayer:pathLayer];

畫圓弧

iOS中角度坐標系示意圖(來自官方API文檔) ![iOS中角度坐標系](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122033902-2102672647.png)
  • 畫圓弧的UIBezierPath相關方法

+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise
center:圓弧的中心,相對所在視圖; radius:圓弧半徑; startAngle:起始點的角度(相對角度坐標系0); endAngle:結束點的角度(相對角度坐標系0); clockwise:是否為順時針方向。

- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise
在原有的線上添加一條弧線 。center:圓弧的中心,相對所在視圖; radius:圓弧半徑; startAngle:起始點的角度(相對角度坐標系0); endAngle:結束點的角度(相對角度坐標系0); clockwise:是否為順時針方向。

在矩形中畫一條圓弧

  • 效果圖
![圓弧](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122033887-945837434.png)
  • 代碼
    UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
    view.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:view];
    
    // 線的路徑
    CGPoint viewCenter = CGPointMake(view.frame.size.width / 2.0, view.frame.size.height / 2.0); // 畫弧的中心點,相對於view
    
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:viewCenter radius:50.0 startAngle:0 endAngle:M_PI_2 clockwise:YES];
    
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.lineWidth = 2;
    pathLayer.strokeColor = [UIColor greenColor].CGColor;
    pathLayer.fillColor = nil; // 默認為blackColor
    pathLayer.path = path.CGPath;
    [view.layer addSublayer:pathLayer];

折線和弧線構成的曲線

  • 效果圖
![折線-弧線-曲線](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122033902-1726615564.png)
  • 代碼
    UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
    view.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:view];
    
    // 線的路徑
    CGPoint viewCenter = CGPointMake(view.frame.size.width / 2.0, view.frame.size.height / 2.0); // 畫弧的中心點,相對於view
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    [path moveToPoint:CGPointMake(50, 50)];
    [path addLineToPoint:CGPointMake(100, 100)];
    
    [path addArcWithCenter:viewCenter radius:50 startAngle:0 endAngle:M_PI clockwise:YES]; // 添加一條弧線
    
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.lineWidth = 2;
    pathLayer.strokeColor = [UIColor greenColor].CGColor;
    pathLayer.fillColor = nil; // 默認為blackColor
    pathLayer.path = path.CGPath;
    [view.layer addSublayer:pathLayer];

二次貝塞爾曲線

二次貝塞爾曲線示意圖 ![二次貝塞爾曲線(來自官方API文檔)](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122034074-1349913227.png)
  • 二次貝賽爾曲線相關方法

- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint
貝塞爾二次曲線,起點用 moveToPoint方法給出;endPoint:貝賽爾曲線終點;controlPoint:控制點;曲線是由起點趨向控制點最后到達終點(不會經過控制點)的曲線。控制點決定曲線的起始方向,起點和終點的距離決定曲線趨向控制點的程度。

設置相同起點,相同控制點,終點不同時貝賽爾曲線比較(即,起點終點距離不同)

  • 效果圖
![不同終點](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122034012-2017111952.png)
  • 代碼
    UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
    view.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:view];

    // 綠色二次貝塞爾曲線
    UIBezierPath *path1 = [UIBezierPath bezierPath];
    [path1 moveToPoint:CGPointMake(0, 100)];
    CGPoint end1Point = CGPointMake(200, 50);
    [path1 addQuadCurveToPoint:end1Point controlPoint:CGPointMake(100, 200)]; // 二次貝塞爾曲線
    CAShapeLayer *path1Layer = [CAShapeLayer layer];
    path1Layer.lineWidth = 2;
    path1Layer.strokeColor = [UIColor greenColor].CGColor;
    path1Layer.fillColor = nil; // 默認為blackColor
    path1Layer.path = path1.CGPath;
    [view.layer addSublayer:path1Layer];
    
    // 紅色二次貝塞爾曲線
    UIBezierPath *path2 = [UIBezierPath bezierPath];
    [path2 moveToPoint:CGPointMake(0, 100)];
    CGPoint end2Point = CGPointMake(100, 50);
    [path2 addQuadCurveToPoint:end2Point controlPoint:CGPointMake(100, 200)]; // 二次貝塞爾曲線
    CAShapeLayer *path2Layer = [CAShapeLayer layer];
    path2Layer.lineWidth = 2;
    path2Layer.strokeColor = [UIColor redColor].CGColor;
    path2Layer.fillColor = nil; // 默認為blackColor
    path2Layer.path = path2.CGPath;
    [view.layer addSublayer:path2Layer];

總結:起點和終點的距離越小,趨向控制點結束越早,趨向終點開始越早,曲線弧度越大。

起點終點相同,控制點不同

  • 效果圖
![不同控制點](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122034043-6460627.png)
  • 代碼
   UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
    view.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:view];

     CGPoint startPoint = CGPointMake(0, 100);
     CGPoint endPoint = CGPointMake(200, 50);
    
    // 綠色二次貝塞爾曲線
    UIBezierPath *path1 = [UIBezierPath bezierPath];
    [path1 moveToPoint:startPoint];
   
    [path1 addQuadCurveToPoint:endPoint controlPoint:CGPointMake(100, 200)]; // 二次貝塞爾曲線
    CAShapeLayer *path1Layer = [CAShapeLayer layer];
    path1Layer.lineWidth = 2;
    path1Layer.strokeColor = [UIColor greenColor].CGColor;
    path1Layer.fillColor = nil; // 默認為blackColor
    path1Layer.path = path1.CGPath;
    [view.layer addSublayer:path1Layer];
    
    // 紅色二次貝塞爾曲線
    UIBezierPath *path2 = [UIBezierPath bezierPath];
    [path2 moveToPoint:startPoint];
    [path2 addQuadCurveToPoint:endPoint controlPoint:CGPointMake(100, 150)]; // 二次貝塞爾曲線
    CAShapeLayer *path2Layer = [CAShapeLayer layer];
    path2Layer.lineWidth = 2;
    path2Layer.strokeColor = [UIColor redColor].CGColor;
    path2Layer.fillColor = nil; // 默認為blackColor
    path2Layer.path = path2.CGPath;
    [view.layer addSublayer:path2Layer];

總結:控制點與起點和終點所在直線偏移距離越大,曲線弧度越大。

三次貝塞爾曲線

三次貝塞爾曲線示意圖(來源於官方API文檔) ![三次貝塞爾曲線示意圖](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919123026621-2076530709.png)
  • UIBezierPath相關方法

- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
三次貝賽爾曲線,起點用 moveToPoint方法給出;endPoint:貝賽爾曲線終點;controlPoint1:控制點1;controlPoint2:控制點2;
曲線是由起點趨向控制點1,之后趨向控制點2,最后到達終點(不會經過控制點)的曲線。在起點和終點所在直線方向上,曲線在起點和控制點1之間,趨向控制點1;在控制點2和終點之間,趨向控制點2.控制點與起點和終點所在直線的偏移影響曲線的偏移程度

  • 效果圖
![三次貝塞爾曲線](http://images2015.cnblogs.com/blog/910416/201609/910416-20160919122034277-1449532994.png)
  • 代碼
  UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
    view.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:view];

     CGPoint startPoint = CGPointMake(0, 100);
     CGPoint endPoint = CGPointMake(200, 100);
    
    // 綠色二次貝塞爾曲線
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:startPoint];
   
    [path addCurveToPoint:endPoint controlPoint1:CGPointMake(50, 75) controlPoint2:CGPointMake(150, 125)]; // 二次貝塞爾曲線
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.lineWidth = 2;
    pathLayer.strokeColor = [UIColor greenColor].CGColor;
    pathLayer.fillColor = nil; // 默認為blackColor
    pathLayer.path = path.CGPath;
    [view.layer addSublayer:pathLayer];

貝塞爾曲線深入學習


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM