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];

贝塞尔曲线深入学习

posted @ 2016-09-19 12:26  Jaesun  阅读(29100)  评论(1编辑  收藏  举报