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

    贝塞尔曲线深入学习

  • 相关阅读:
    Serverless
    使用excelJS实现excel文件转json文件
    使用excelJS实现json文件转excel文件
    git rebase 和 git merge的异同
    JS 箭头函数与普通函数的区别
    JS 节流函数(throttle)与防抖函数(debounce)
    http协议解析
    前端必会的js知识总结整理
    前端必会css整理
    推荐几个有趣的在线调试工具
  • 原文地址:https://www.cnblogs.com/jaesun/p/iOS-CAShapeLayerUIBezierPath-hua-xian.html
Copyright © 2020-2023  润新知