Quartz 2D

作者: CoderCurtis | 来源:发表于2017-05-24 16:34 被阅读24次

    Quartz 2D:

    • Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac OS X系统(跨平台,纯C语言)。包含在Core Graphics框架中。

    Quartz 2D能完成的工作:

    • 绘制图形: 线条/三角形/矩形/圆/弧等
    • 绘制文字
    • 绘制/生成图片
    • 读取/生成PDF
    • 自定义UI控件
    • ... ...

    Quartz 2D绘图主要步骤:

    • 通过Quartz 2D原生API绘图:

      • 获取[图形上下文]对象
      • 向[图形上下文]对象中添加[路劲]
      • 渲染(把[图形上下文]中的图形绘制到对应的设备上)

    图形上下文CGContextRef

    • 图形上下文(Graphics Context): 是一个CGContextRef类型的数据
    • 图形上下文中主要包含如下信息:
      • 绘制路径(各种各样的图形)
      • 绘图状态(颜色、线宽、样式、旋转、缩放、平移、图片剪裁区域等)
      • 输出目标(绘制到什么地方去?UIView、PDF、打印机等)

    图形上下文:

    提供了以下几种图形上下文:

    • Bitmap Graphics Context --效果画到图片上
    • PDF Graphics Context --画到PDF上
    • Window Graphics Context --画到Mac电脑窗口上
    • Layer Graphics Context(UI 控件) --画到UI控件上
    • Printer Graphics Context --画到打印机

    PS: 相同的一套绘图序列,指定不同的Graphics Context, 就可以将相同的图像绘制到不同的目标上。

    通过UIBezierPath + 图形上下文绘制图形:

    • 获取图形上下文对象
    • 创建UIBezierPath对象
    • 向UIBezierPath对象中绘制图形
    • 把UIBezierPath对象添加到上下文中
    • 把上下文对象渲染到设备上

    PS: UIBezierPath对象可以独立使用,无需手动获取 图形上下文 对象,这里为了更好的理解 图形上下文对象,采取手动获取图形上下文对象的方式来绘图。

    自定义UIView时,实现文件中:

    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect {
        // Drawing code
    }
    */
    

    即:在drawRect:方法中才能取得跟view相关联的图形上下文 我们才能绘制各种图形。

    drawRect: 方法仅在view第一次显示在Window上时调用一次,如果想重新调用 需要手动调用setNeedsDisplay或setNeedsDisplayInRect:方法。

    不可手动调用drawRect: 方法,该方法是由系统在需要调用的时候调用--不能主动调用该方法。

    • Quartz 2D原生API绘制:

      • 绘制直线:
    //1.获取图形上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        
        //2. 绘制各种路径
        //2.1 设置一个起点
        CGContextMoveToPoint(ref, 20, 100);
        //2.2 设置一个终点
        CGContextAddLineToPoint(ref, 100, 160);
        //3. 渲染
        CGContextStrokePath(ref);
    
    • 绘制三角形:
    //1.获取图形上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        
        //2. 绘制各种路径
        //2.1 设置一个起点
        CGContextMoveToPoint(ref, 20, 100);
        //2.2 设置一个终点
        CGContextAddLineToPoint(ref, 100, 160);
        //2.3 再添加一个终点
        CGContextAddLineToPoint(ref, 150, 100);
        
        //2.4 关闭路径
        CGContextClosePath(ref);
        
        //3. 渲染
        CGContextStrokePath(ref);
    
    • UIBezierPath绘制图形:
      • 绘制直线:
    //1. 获取图形上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        //2. 创建UIBezierPath对象
        UIBezierPath *path = [UIBezierPath bezierPath];
        //3. 向UIBezierPath添加路径
        [path moveToPoint:CGPointMake(30, 100)];
        [path addLineToPoint:CGPointMake(300, 300)];
        //4. 把UIBezierPath对象添加到上下文中
        CGContextAddPath(ref, path.CGPath);
        //设置状态信息
        //i. 线宽
        CGContextSetLineWidth(ref, 10);
        //ii. 设置线段两端样式
        /*
         typedef CF_ENUM(int32_t, CGLineCap) {
         kCGLineCapButt,        //默认
         kCGLineCapRound,
         kCGLineCapSquare
         };
         */
        CGContextSetLineCap(ref, kCGLineCapRound);
        //iii. 设置线段连接处的样式
        /*
         typedef CF_ENUM(int32_t, CGLineJoin) {
         kCGLineJoinMiter,      //默认
         kCGLineJoinRound,
         kCGLineJoinBevel
         };
         */
        CGContextSetLineJoin(ref, kCGLineJoinRound);
        //iV. 设置绘图颜色
        //    [[UIColor redColor] setStroke]; //画边的时候使用红色 --仅用于渲染时 为kCGPathStroke时
        //    [[UIColor yellowColor] setFill];    //设置填充时颜色 --kCGPathFill
        [[UIColor blueColor] set];  //填充和描边 使用同一颜色
        //5. 渲染
        //    CGContextStrokePath(ref);
        //上面所有的设置状态的代码,都会将状态应用于当前上下文中的所有路径
        //    CGContextDrawPath(ref, kCGPathStroke);    //与[[UIColor redColor] setStroke];对应
        //    CGContextDrawPath(ref, kCGPathFill);      //与[[UIColor yellowColor] setFill];对应
        CGContextDrawPath(ref, kCGPathFillStroke);  //既填充也描边    //与[[UIColor blueColor] set];对应
    
    • 绘制三角形:
    //1. 获取上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        //2. 创建UIBezierPath对象
        UIBezierPath *path = [UIBezierPath bezierPath];
        //3. 向UIBezierPath添加路径
        [path moveToPoint:CGPointMake(100, 200)];
        [path addLineToPoint:CGPointMake(160, 300)];
        [path addLineToPoint:CGPointMake(220, 200)];
        //关闭路径
        [path closePath];
        //4. 把UIBezierPath对象添加到上下文中
        CGContextAddPath(ref, path.CGPath); //OC对象 转 C语言
        //5. 渲染
        //    CGContextStrokePath(ref);
        //or
        /*
         typedef CF_ENUM (int32_t, CGPathDrawingMode) {
         kCGPathFill,
         kCGPathEOFill,
         kCGPathStroke,
         kCGPathFillStroke,
         kCGPathEOFillStroke
         };
         */
        CGContextDrawPath(ref, kCGPathStroke);
    
    • 绘制矩形:
    //获取上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        //创建UIBezierPath
        //向UIBezierPath中添加路径
        //绘制矩形
        UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 200, 100)];
        //把UIBezierPath添加到上下文中
        CGContextAddPath(ref, path.CGPath);
        //渲染
        /*
         typedef CF_ENUM (int32_t, CGPathDrawingMode) {
         kCGPathFill,
         kCGPathEOFill,
         kCGPathStroke,
         kCGPathFillStroke,
         kCGPathEOFillStroke
         };
         */
        CGContextDrawPath(ref, kCGPathStroke);
        //    CGContextDrawPath(ref, kCGPathFill); //填充
    
    • 绘制椭圆:
    //获取上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        //创建UIBezierPath
        //向UIBezierPath中添加路径
        UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 200, 100)];
        //把UIBezierPath添加到上下文中
        CGContextAddPath(ref, path.CGPath);
        //渲染
        /*
         typedef CF_ENUM (int32_t, CGPathDrawingMode) {
         kCGPathFill,
         kCGPathEOFill,
         kCGPathStroke,
         kCGPathFillStroke,
         kCGPathEOFillStroke
         };
         */
        CGContextDrawPath(ref, kCGPathStroke);
        //    CGContextDrawPath(ref, kCGPathFill); //填充
    
    • 绘制圆形:

      • 第一种方式: 画椭圆方法 --宽高相等
    //获取上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        //创建UIBezierPath
        //向UIBezierPath中添加路径
        UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 100, 100)];
        //把UIBezierPath添加到上下文中
        CGContextAddPath(ref, path.CGPath);
        //渲染
        /*
         typedef CF_ENUM (int32_t, CGPathDrawingMode) {
         kCGPathFill,
         kCGPathEOFill,
         kCGPathStroke,
         kCGPathFillStroke,
         kCGPathEOFillStroke
         };
         */
        CGContextDrawPath(ref, kCGPathStroke);
        //    CGContextDrawPath(ref, kCGPathFill); //填充
    
    - 第二种方式: 绘制矩形 --宽高相等 cornerRadius: 边长/2.0
    
    //获取上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        //创建UIBezierPath
        //向UIBezierPath中添加路径
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 50, 100, 100) cornerRadius:50];
        //把UIBezierPath添加到上下文中
        CGContextAddPath(ref, path.CGPath);
        //渲染
        /*
         typedef CF_ENUM (int32_t, CGPathDrawingMode) {
         kCGPathFill,
         kCGPathEOFill,
         kCGPathStroke,
         kCGPathFillStroke,
         kCGPathEOFillStroke
         };
         */
        CGContextDrawPath(ref, kCGPathStroke);
        //    CGContextDrawPath(ref, kCGPathFill); //填充
    
    - 第三种方式: 绘制圆弧方式画一个圆
    
    //获取上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        //创建UIBezierPath
        //向UIBezierPath中添加路径
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:50 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
        //把UIBezierPath添加到上下文中
        CGContextAddPath(ref, path.CGPath);
        //渲染
        /*
         typedef CF_ENUM (int32_t, CGPathDrawingMode) {
         kCGPathFill,
         kCGPathEOFill,
         kCGPathStroke,
         kCGPathFillStroke,
         kCGPathEOFillStroke
         };
         */
        CGContextDrawPath(ref, kCGPathStroke);
        //    CGContextDrawPath(ref, kCGPathFill); //填充
    
    • 绘制圆弧:
    //获取上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        //创建UIBezierPath
        //向UIBezierPath中添加路径
        //画弧
        //ArcCenter: 圆心
        //radius: 半径
        //startAngle: 开始弧度  --1弧度 = 180度
        //endAngle: 结束弧度
        //绘制一个弧 clockwise: 顺时针或逆时针
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:50 startAngle:0 endAngle:M_PI_2 clockwise:NO];
        //把UIBezierPath添加到上下文中
        CGContextAddPath(ref, path.CGPath);
        //渲染
        /*
         typedef CF_ENUM (int32_t, CGPathDrawingMode) {
         kCGPathFill,
         kCGPathEOFill,
         kCGPathStroke,
         kCGPathFillStroke,
         kCGPathEOFillStroke
         };
         */
        CGContextDrawPath(ref, kCGPathStroke);
        //    CGContextDrawPath(ref, kCGPathFill); //填充
    
    • 绘制圆环:
    //获取上下文
        CGContextRef ref = UIGraphicsGetCurrentContext();
        //创建UIBezierPath
        //向UIBezierPath中添加路径
        //画圆环
        //直接画一个圆 设置线宽 --推荐使用这种方式
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:50 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
        CGContextSetLineWidth(ref, 20);   //线宽 里外各一半
        //把UIBezierPath添加到上下文中
        CGContextAddPath(ref, path.CGPath);
        //渲染
        /*
         typedef CF_ENUM (int32_t, CGPathDrawingMode) {
         kCGPathFill,
         kCGPathEOFill,
         kCGPathStroke,
         kCGPathFillStroke,
         kCGPathEOFillStroke
         };
         */
        CGContextDrawPath(ref, kCGPathStroke);
        //    CGContextDrawPath(ref, kCGPathFill); //填充
    

    参考资料:
    传智播客教程
    iOS-Quartz2D

    代码

    相关文章

      网友评论

          本文标题:Quartz 2D

          本文链接:https://www.haomeiwen.com/subject/ethoxxtx.html