Quartz 2D 绘图技术

作者: BradleyJohnson | 来源:发表于2015-07-06 23:32 被阅读2164次

    Quartz 2D。是 iOS 和 Mac OS X 环境下的2D绘图引擎。Quartz 2D 也被称为 Core Graphics,缩写前缀为CG,Quartz 2D 与 Quartz Compositor 统称为 Quartz,Quartz 原本是 Mac OS X 的 Darwin 核心之上的绘图技术。它的 API 接口都是基于 C 的。

    1.绘制原理

    摆事实,讲道理。在 iOS 中,所有的绘制都离不开 UIView ,绘制都发生在 UIView 对象区域内。在绘制发生的时候,如果是使用的系统提供的视图,则绘制工作会自动发生。若不是,则我们需要重写 drawRect: 方法,在此方法中提供相应的绘制代码。

    2.绘制周期

    通常我们会设置一个标志,在每一轮的事件中扫描标志,看是否需要重新绘制,如果需要我们则调用 drawRect: 方法进行绘制。于是我们除了 drawRect: ,还有 setNeedsDisplaysetNeedsDisplayInRect: 方法供我们使用。他们分别的作用如下:

    setNeedsDisplay:设置整个视图重新绘制。

    setNeedsDisplayInRect::设置部分区域的视图重新绘制。

    3.绘制 - Quartz 图形上下文

    Quartz 图形上下文是包含绘制系统执行后,绘制命令所需要的信息,定义了各种基本的绘制参数,比如绘制使用的颜色、裁剪区域、线段的宽度及风格信息、文体信息、合成选项以及几个其他信息。

    在调用 drawRect: 方法之前,视图对象会自动配置其绘制环境使代码能够立即执行进行绘制。作为这些配置的一部分,UIView 对象会为当前绘制环境创建一个图形上下文(对应于 CGContextRef 封装类型)。我们可以在 drawRect: 方法中通过 UIGraphicsGetCurrentContext()来获取和访问图形上下问对象,再对当前的图形进行定制的绘制。

    4.绘制 - 具体实现

    4.1 绘制一条直线
    #import "BJView.h"
    
    @implementation BJView
    
    - (void)drawRect:(CGRect)rect {
    
        //获取图形上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        //设置线条颜色
        CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
    
        //设置线条宽度
        CGContextSetLineWidth(context, 2.f);
    
        //设置线条起点和终点的样式
        CGContextSetLineCap(context, kCGLineCapRound);
    
        //设置线条的转角的样式
        CGContextSetLineJoin(context, kCGLineJoinRound);
    
    
        // 绘制线方式 1
        //    CGContextMoveToPoint(context, 100, 120);
        //    CGContextAddLineToPoint(context, 150, 120);
        
        // 绘制线方式 2
        CGPoint apoint[2];
        apoint[0] = CGPointMake(100, 120);
        apoint[1] = CGPointMake(150, 120);
        CGContextAddLines(context, apoint, 2);
    
        //是否闭合路径
        //    CGContextClosePath(context);
    
        CGContextDrawPath(context, kCGPathFillStroke);
    }
    
    @end
    

    效果:


    直线
    4.2 绘制一条折线(闭合且填充内容,相当于三角形)
    #import "BJView.h"
    
    @implementation BJView
    
    - (void)drawRect:(CGRect)rect {
    
        //获取图形上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        //设置边框颜色
        CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
    
        //设置填充颜色
        CGContextSetRGBFillColor(context, 0, 1, 0, 1);
    
        //设置线条宽度
        CGContextSetLineWidth(context, 2.f);
    
        //设置线条起点和终点的样式
        CGContextSetLineCap(context, kCGLineCapRound);
    
        //设置线条的转角的样式
        CGContextSetLineJoin(context, kCGLineJoinRound);
    
    
        // 绘制线方式 1
        //    CGContextMoveToPoint(context, 100, 120);
        //    CGContextAddLineToPoint(context, 150, 120);
        //    CGContextAddLineToPoint(context, 150, 180);
    
        // 绘制线方式 2
        CGPoint apoint[3];
        apoint[0] = CGPointMake(100, 120);
        apoint[1] = CGPointMake(150, 120);
        apoint[2] = CGPointMake(150, 180);
        CGContextAddLines(context, apoint, 3);
    
        //闭合路径
        CGContextClosePath(context);
    
        CGContextDrawPath(context, kCGPathFillStroke);
    }
    
    @end
    

    效果:


    折线
    4.3 绘制一个矩形
    #import "BJView.h"
    
    @implementation BJView
    
    - (void)drawRect:(CGRect)rect {
    
        //获取图形上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        //设置边框颜色
        CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
    
        //设置填充颜色
        CGContextSetRGBFillColor(context, 0, 1, 0, 1);
    
        //设置线条宽度
        CGContextSetLineWidth(context, 2.f);
    
        //设置线条起点和终点的样式
        //    CGContextSetLineCap(context, kCGLineCapRound);
    
        //设置线条的转角的样式
        CGContextSetLineJoin(context, kCGLineJoinRound);
    
        // 通过绘制线的方式 1
        //    CGContextMoveToPoint(context, 100, 100);
        //    CGContextAddLineToPoint(context, 150, 100);
        //    CGContextAddLineToPoint(context, 150, 150);
        //    CGContextAddLineToPoint(context, 100, 150);
    
        // 通过绘制线的方式 2
        //    CGPoint apoint[4];
        //    apoint[0] = CGPointMake(100, 100);
        //    apoint[1] = CGPointMake(150, 100);
        //    apoint[2] = CGPointMake(150, 150);
        //    apoint[3] = CGPointMake(100, 150);
        //    CGContextAddLines(context, apoint, 4);
    
        // 绘制矩形方法
        CGContextAddRect(context, CGRectMake(100, 100, 50, 50));
    
        //闭合路径
        //    CGContextClosePath(context);
    
        CGContextDrawPath(context, kCGPathFillStroke);
    }
    
    @end
    

    效果:


    矩形
    4.4 绘制一个圆(椭圆的特殊形态)
    #import "BJView.h"
    
    @implementation BJView
    
    - (void)drawRect:(CGRect)rect {
    
        //获取图形上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        //设置边框颜色
        CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
    
        //设置填充颜色
        CGContextSetRGBFillColor(context, 0, 1, 0, 1);
    
        //设置线条宽度
        CGContextSetLineWidth(context, 2.f);
    
        //设置线条起点和终点的样式
        //    CGContextSetLineCap(context, kCGLineCapRound);
    
        //设置线条的转角的样式
        //    CGContextSetLineJoin(context, kCGLineJoinRound);
            
        // 绘制圆方法(其实所绘制的圆为所绘制用的Rect的矩形的内切圆,当宽度等于高度时,即为正圆)
        CGContextAddEllipseInRect(context, CGRectMake(100, 100, 200, 100));
    
        //闭合路径
        //    CGContextClosePath(context);
    
        CGContextDrawPath(context, kCGPathFillStroke);
    }
    
    @end
    

    效果:


    4.5 绘制一段圆弧(闭合且填充内容,相当于扇形)
    #import "BJView.h"
    
    #define arc(angle) ((angle)*(M_PI/180.0))
    
    @implementation BJView
    
    - (void)drawRect:(CGRect)rect {
    
        //获取图形上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        //设置边框颜色
        CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
    
        //设置填充颜色
        CGContextSetRGBFillColor(context, 0, 1, 0, 1);
    
        //设置线条宽度
        CGContextSetLineWidth(context, 2.f);
    
        //设置线条起点和终点的样式
        CGContextSetLineCap(context, kCGLineCapRound);
    
        //设置线条的转角的样式
        //    CGContextSetLineJoin(context, kCGLineJoinRound);
            
        // 绘制圆弧方法1 (参数由左至右分别是,图形上下文、圆心x、圆心y、半径、起始弧度、结束弧度、圆弧伸展的方向(0为顺时针,1为逆时针))
        CGContextAddArc(context, 150, 100, 100, arc(0), arc(160), 0);
    
        // 绘制圆弧方法2,由起始点、结束点分别与中间节点连线,同时以半径切过这两边则确定一段圆弧(不建议使用,因为理解不方便)
        // CGContextMoveToPoint(context, 100, 100);
        // CGContextAddArcToPoint(context, 150, 100, 150, 150, 50);
    
        //闭合路径
        CGContextClosePath(context);
    
        CGContextDrawPath(context, kCGPathFillStroke);
    }
    
    @end
    

    效果:


    圆弧
    4.6 绘制一段文字
    #import "BJView.h"
    
    #define arc(angle) ((angle)*(M_PI/180.0))
    
    @implementation BJView
    
    - (void)drawRect:(CGRect)rect {
    
        NSString * str = @"BradleyJohnson";
        NSMutableDictionary * attributes = [NSMutableDictionary dictionary];
        attributes[NSFontAttributeName] = [UIFont systemFontOfSize:20];         attributes[NSForegroundColorAttributeName] = [UIColor purpleColor];
        attributes[NSBackgroundColorAttributeName] = [UIColor whiteColor];
        [str drawInRect:CGRectMake(100, 100, 200, 30) withAttributes:attributes];
    
    }
    
    @end
    

    效果:


    文字
    4.6 绘制一张图片
    #import "BJView.h"
    
    @implementation BJView
    
    - (void)drawRect:(CGRect)rect {
    
        UIImage * img = [UIImage imageNamed:@"bradleyJohnson.jpg"];
        
        // 在指定的范围内绘制图片,有可能引起图片拉伸
        [img drawInRect:rect];
    }
    
    @end
    

    效果:


    图片

    5.绘制 - 贝塞尔曲线绘制

    贝塞尔曲线,使用UIBezierPath类可以创建基于矢量的路径,这个类在UIKit中。它基本可以实现我们上面利用图形上下文做到的功能。
    



    例如:

    #import "BJView.h"
    
    @implementation BJView
    
    - (void)drawRect:(CGRect)rect {
    
        [[UIColor redColor] setStroke];    
    
        UIBezierPath * path = [UIBezierPath bezierPath];
        path.lineWidth = 2.0;
        path.lineCapStyle = kCGLineCapRound;
        path.lineJoinStyle = kCGLineJoinBevel;
    
        [path moveToPoint:CGPointMake(10, 20)];
        [path addLineToPoint:CGPointMake(50, 20)];
    
        [path closePath];
    
        [path stroke];
    }
    
    @end
    

    这就可以轻易的绘制出一条直线,效果如图:

    贝塞尔



    同样的,我们也可以轻易的绘制出三角形、矩形、椭圆(圆)、圆弧如下:

    #import "BJView.h"
    #define arc(angle) ((angle)*(M_PI/180.0))
    
    @implementation BJView
    
    - (void)drawRect:(CGRect)rect {
    
        /* 三角形 */
        [[UIColor redColor] setStroke];
    
        UIBezierPath * path = [UIBezierPath bezierPath];
        path.lineWidth = 2.0;
        path.lineCapStyle = kCGLineCapRound;
        path.lineJoinStyle = kCGLineJoinBevel;
    
        [path moveToPoint:CGPointMake(10, 20)];
        [path addLineToPoint:CGPointMake(50, 20)];
        [path addLineToPoint:CGPointMake(50, 60)];
    
        [path closePath];
    
        [path stroke];
        
        /* 圆弧 */
        [[UIColor redColor] setStroke];
    
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100,100) radius:100 startAngle:0 endAngle:arc(135) clockwise:YES];
        
        [path stroke];
        
        /* 矩形 */
        [[UIColor redColor] setStroke];
    
        UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(20, 20, 100, 100)];
        
        [path stroke];
        
        /* 椭圆(圆) */
        [[UIColor redColor] setStroke];
    
        UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(20, 20, 100, 100)];
        
        [path stroke];
    }
    
    @end
    

    当然最经典的就是,我们可以绘制二次和三次的贝塞尔曲线:

    #import "BJView.h"
    
    @implementation BJView
    
    - (void)drawRect:(CGRect)rect {
        
        [[UIColor redColor] setStroke];
    
        UIBezierPath *path = [UIBezierPath bezierPath];
    
        [path moveToPoint:CGPointMake(20, 100)];
    
        // 绘制二次贝塞尔曲线
        //    [path addQuadCurveToPoint:CGPointMake(120, 100) controlPoint:CGPointMake(70, 150)];
        
        // 绘制三次贝塞尔曲线
        [path addCurveToPoint:CGPointMake(120, 100) controlPoint1:CGPointMake(45, 150) controlPoint2:CGPointMake(95, 50)];
    
    
        [path stroke];
    }
    
    @end
    

    效果如下:


    贝塞尔多次









    如果你想要看到源码,可以到我的github上下载使用:Demo


    如果你喜欢我的文章,请不要吝啬你的喜欢和关注,这是我的个人博客.

    相关文章

      网友评论

      本文标题:Quartz 2D 绘图技术

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