二维绘图引擎Quartz 2D

转载自:http://www.jianshu.com/p/24e99ecd3b42



Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统

Quartz 2D能完成的工作:

  • 绘制图形 : 线条/三角形/矩形/圆/弧等
  • 绘制文字
  • 绘制/生成图片(图像)
  • 读取/生成PDF
  • 截图/裁剪图片
  • 自定义UI控件 (重要)
图形上下文

图形上下文(Graphics Context):是一个CGContextRef类型的数据

图形上下文的作用:

  • 保存绘图信息、绘图状态
  • 决定绘制的输出目标(绘制到什么地方去?)
    (输出目标可以是PDF文件、Bitmap或者显示器的窗口上)
    相同的一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上

Quartz2D提供了以下几种类型的Graphics Context:

  • Bitmap Graphics Context
  • PDF Graphics Context
  • Window Graphics Context
  • Layer Graphics Context
  • Printer Graphics Context
drawRect:方法
  • 如何利用Quartz2D绘制东西到view上?

    首先,得有图形上下文,因为它能保存绘图信息,并且决定着绘制到什么地方去

    其次,那个图形上下文必须跟view相关联,才能将内容绘制到view上面

  • 如何利用Quartz2D自定义view?(自定义UI控件)

    1.新建一个类,继承自UIView

    2.实现- (void)drawRect:(CGRect)rect方法,然后在这个方法中取得跟当前view相关联的图形上下文

    3.绘制相应的图形内容

    4.利用图形上下文将绘制的所有内容渲染显示到view上面

  • 为什么要实现drawRect:方法才能绘图到view上?

    因为在drawRect:方法中才能取得跟view相关联的图形上下文

  • drawRect:方法在什么时候被调用?

    当view第一次显示到屏幕上时(被加到UIWindow上显示出来)

    调用view的setNeedsDisplay(重绘)或者setNeedsDisplayInRect:时

    注意:调用setNeedsDisplay方法并不会立马调用drawRect:方法,只是设了一个标志,当屏幕下一次刷新的时候才去调用drawRect:方法。(屏幕每秒刷新60次)

画直线
/**
 *   在drawRect:方法中系统已经帮你创建好了一个跟view相关联的上下文(layer上下文),只需要获取就好了
 *   作用:专门用来绘图
 *   什么时候调用:当view显示的时候自动调用
 *   @param rect:当前view的bounds
 *
 */
- (void)drawRect:(CGRect)rect {
    //1.获取图形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    //上下文的状态(线的粗细、颜色、链接样式等)
    //设置线的粗细
    CGContextSetLineWidth(ctx, 10);
    //设置链接点的样式
    /**
     typedef CF_ENUM(int32_t, CGLineJoin) {
        kCGLineJoinMiter,
        kCGLineJoinRound,
        kCGLineJoinBevel
     };
     */
    CGContextSetLineJoin(ctx, kCGLineJoinRound);
    //设置线的顶角样式
    /**
     typedef CF_ENUM(int32_t, CGLineCap) {
        kCGLineCapButt,
        kCGLineCapRound,
        kCGLineCapSquare
     };
     */

    CGContextSetLineCap(ctx, kCGLineCapRound);
    //设置颜色(注意:这里设置颜色必须跟渲染方式一致,否则设置不上颜色)
//    [[UIColor redColor]setFill]; //渲染方式为Fill
//    [[UIColor redColor]setStroke];  //渲染方式为Stroke
    [[UIColor redColor]set];  //两种渲染方式均可,推荐使用

    //2. 绘制路径
    UIBezierPath *path = [UIBezierPath bezierPath];
    //2.1 设置起点
    [path moveToPoint:CGPointMake(50, 250)];
    //2.2 添加一根线到终点
    [path addLineToPoint:CGPointMake(250, 50)];

    //画第二条直线(新起点)
    [path moveToPoint:CGPointMake(100, 250)];
    [path addLineToPoint:CGPointMake(250, 100)];

    //把上一条线的终点当做起点来画第二条线
    [path addLineToPoint:CGPointMake(250, 250)];

    //3.把绘制的内容添加到上下文中
    // UIBezierPath:UIKit框架   --->   CGPathRef:CoreGraphics框架
    CGContextAddPath(ctx, path.CGPath);

    //4.把上下文的内容显示到view上(渲染到view的layer上)渲染的方式有两种Stroke(描边)、Fill(填充)
    CGContextStrokePath(ctx);
}
画曲线
//画曲线
- (void)drawQuadCurve{
    //1.获取图形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //2.绘制图形
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(50, 250)];
    //添加一条曲线
    [path addQuadCurveToPoint:CGPointMake(250, 250) controlPoint:CGPointMake(50, 50)];

    //3.把绘制的内容添加到上下文中
    CGContextAddPath(ctx, path.CGPath);
    //4.把上下文的内容渲染到view上
    CGContextStrokePath(ctx);
}

图片来自苹果官方文档

画矩形
- (void)drawRect:(CGRect)rect {

    //1.获取图形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    //设置颜色
    [[UIColor redColor]set];
    //2.绘制路径
    //画矩形
    //    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 100, 100)];
    //画圆角矩形
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 50, 100, 100) cornerRadius:50];
    //3.把路径添加到上下文
    CGContextAddPath(ctx, path.CGPath);
    //4.把上下文渲染到view上
    //描边
    //    CGContextStrokePath(ctx);
    //填充
    CGContextFillPath(ctx);

}
画椭圆
- (void)drawRect:(CGRect)rect {

    //画椭圆
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 100, 50)];
    //画矩形
//    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 100, 50)];
    //画线
    [path moveToPoint:CGPointMake(50, 250)];
    [path addLineToPoint:CGPointMake(250, 250)];
    //设置颜色
    [[UIColor redColor]set];
    //设置线条的粗细
    [path setLineWidth:10];
    //[path stroke] 底层:
    //1.获取图形上下文 -> 2.绘制路径 -> 3.把路径添加到上下文 -> 4.把上下文渲染到view上
    [path stroke];
    //填充
//    [path fill];
}
画弧
- (void)drawRect:(CGRect)rect {

    //画弧
    //ArcCenter:弧所在圆的圆心
    //radius:弧所在圆的半径
    //startAngle:起始角度
    //endAngle:结束角度
    //clockwise: YES:顺时针 NO:逆时针

    //不能直接使用self.center :因为self.center坐标是相对于他的父控件
    CGPoint center = CGPointMake(rect.size.width * 0.5, rect.size.height * 0.5);
    CGFloat radius = rect.size.width * 0.5 - 10;
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0 endAngle:M_PI_4 clockwise:YES];

    [path stroke];

}
画扇形
- (void)drawRect:(CGRect)rect {
    //画弧
    //ArcCenter:弧所在圆的圆心
    //radius:弧所在圆的半径
    //startAngle:起始角度
    //endAngle:结束角度
    //clockwise: YES:顺时针 NO:逆时针

    //不能直接使用self.center :因为self.center坐标是相对于他的父控件
    CGPoint center = CGPointMake(rect.size.width * 0.5, rect.size.height * 0.5);
    CGFloat radius = rect.size.width * 0.5 - 10;
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0 endAngle:M_PI_4 clockwise:YES];

    //画扇形
    //添加一根线到圆心
    [path addLineToPoint:center];

    //关闭路径:从路径终点添加一根线到路径的起点
    [path closePath];

    //填充之前,会自动关闭路径
    //    [path fill];
    [path stroke];
    }
画饼图
#import "PieView.h"

@implementation PieView

- (void)drawRect:(CGRect)rect {

    NSArray *dataArray = @[@15,@20,@5,@10,@50];

    CGPoint center = CGPointMake(rect.size.width * 0.5, rect.size.height * 0.5);
    CGFloat redius = rect.size.width * 0.5 - 10;
    CGFloat startA = 0;
    CGFloat angle = 0;
    CGFloat endA = 0;

    for (NSNumber *num in dataArray) {

        startA = endA;
        angle = num.intValue / 100.0 * M_PI * 2;
        endA = startA + angle;
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:redius startAngle:startA endAngle:endA clockwise:YES];
        //随机颜色
        [[self randomColor]set];
        //弧的终点向圆心画一条线
        [path addLineToPoint:center];
        //填充
        [path fill];
    }
}

//随机颜色
- (UIColor *)randomColor{

    CGFloat r = arc4random_uniform(256) / 255.0;
    CGFloat g = arc4random_uniform(256) / 255.0;
    CGFloat b = arc4random_uniform(256) / 255.0;
    return [UIColor colorWithRed:r green:g blue:b alpha:1];
}

@end

饼图

UIKit绘图

画文字

- (void)drawRect:(CGRect)rect {
    // Drawing code

    NSString *str = @"Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统";

    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    //设置文字大小
    dict[NSFontAttributeName] = [UIFont systemFontOfSize:20];
    //设置文字颜色
    dict[NSForegroundColorAttributeName] = [UIColor greenColor];
    //设置描边宽度
    dict[NSStrokeWidthAttributeName] = @2;
    //设置描边颜色
    dict[NSStrokeColorAttributeName] = [UIColor blueColor];
    //设置阴影
    NSShadow *shadow = [[NSShadow alloc] init];
    //设置阴影的便宜量
    shadow.shadowOffset = CGSizeMake(10, 10);
    //设置阴影颜色
    shadow.shadowColor = [UIColor greenColor];
    //设置阴影模糊程序
    shadow.shadowBlurRadius = 1;
    dict[NSShadowAttributeName] = shadow;

    /**
     AtPoint:文字所画的位置
     withAttributes:描述文字的属性.
     */
    //不会自动换行
    [str drawAtPoint:CGPointZero withAttributes:dict];
    //会自动换行.
    [str drawInRect:self.bounds withAttributes:dict];
}

画图片

- (void)drawRect:(CGRect)rect {
    // Drawing code
    //1.加载图片
    UIImage *image = [UIImage imageNamed:@"agt"];

    //绘制出来的图片,是保持原来图片大小
    [image drawAtPoint:CGPointZero];
    //把图片填充到这个rect当中.
    [image drawInRect:rect];
    //添加裁剪区域 .把超区裁剪区域以外都裁剪掉
    UIRectClip(CGRectMake(0, 0, 50, 50));
    //平铺
    [image drawAsPatternInRect:self.bounds];

    //快速的画出一个矩形
    [[UIColor blueColor] set];
    UIRectFill(CGRectMake(10, 10, 100, 100));
}
上下文状态栈
- (void)drawRect:(CGRect)rect {
    // Drawing code
    //1.获取图形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //2.描述路径
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(10, 100)];
    [path addLineToPoint:CGPointMake(150, 100)];

    /*******保存当前上下文的状态到上下文状态栈*********/
    CGContextSaveGState(ctx);

    //修改状态
    CGContextSetLineWidth(ctx, 10);
    [[UIColor redColor]set];

    //3.将路径添加到上下文
    CGContextAddPath(ctx, path.CGPath);
    //4.将上下文渲染到view上
    CGContextStrokePath(ctx);

    //2.描述路径
    UIBezierPath *path2 = [UIBezierPath bezierPath];
    [path2 moveToPoint:CGPointMake(100, 10)];
    [path2 addLineToPoint:CGPointMake(100, 150)];

    //修改状态
//    CGContextSetLineWidth(ctx, 1);
//    [[UIColor blackColor]set];
    /*******从上下文状态栈中取出最上面的状态*********/
    CGContextRestoreGState(ctx);
    //3.将路径添加到上下文
    CGContextAddPath(ctx, path2.CGPath);
    //4.将上下文渲染到view上
    CGContextStrokePath(ctx);
}
@end

绘制不同的状态

图形上下文的矩阵操作
- (void)drawRect:(CGRect)rect {
    // Drawing code

    //1.获取图形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //2.绘制路径
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 100, 50)];

    //把路径添加到上下文中之前可以做一些矩阵操作
    //平移
    CGContextTranslateCTM(ctx, 100, 100);
    //旋转
    CGContextRotateCTM(ctx, M_PI_4);
    //缩放
    CGContextScaleCTM(ctx, 1.5, 1.5);


    //3.把路径添加到图形上下文中
    CGContextAddPath(ctx, path.CGPath);
    //4.把上下文渲染到view上
    CGContextFillPath(ctx);
}

当然,在实际开发中我们不需要自己去画折线图、饼图、各种统计图... ...

一个很好的第三方库 Charts 是一个简单、面向对象、为设计者和开发者准备的图表绘制工具库


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值