• iOS学习笔记08 Quartz2D绘图


    ###一、Quartz2D简单介绍 在iOS中常用的绘图框架就是Quartz2DQuartz2DCore Graphics框架的一部分,我们日常开发使用的所有UIKit组件都是由Core Graphics进行绘制的 ######在iOS中Quartz2D绘图的一般步骤:

    1. 获取绘制上下文
    1. 创建并设置路径
    2. 将路径添加进绘制上下文中
    3. 设置上下文状态
    4. 绘制路径
    5. 释放路径

    UIKit默认为我们提供了一个图形上下文,在UI控件的drawRect:方法中调用UIGraphicsGetCurrentContext()获取图形上下文 ######下面是使用实例,在自定义UIView类内定义:

    #pragma mark 绘图   
    - (void)drawRect:(CGRect)rect{ //绘图只能在此方法中调用,否则无法得到当前图形上下文
    	//1.取得图形上下文对象    
    	CGContextRef context = UIGraphicsGetCurrentContext();    
    	//2.创建路径对象    
    	CGMutablePathRef path = CGPathCreateMutable();    
    	CGPathMoveToPoint(path, nil, 20, 50);//移动到指定位置(设置路径起点)    
    	CGPathAddLineToPoint(path, nil, 20, 100);//绘制直线(从起始位置开始)    
    	CGPathAddLineToPoint(path, nil, 300, 100);//绘制另外一条直线(从上一直线终点开始绘制)    
    	//3.添加路径到图形上下文    
    	CGContextAddPath(context, path);    
    	//4.设置图形上下文状态属性    
    	CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1);//设置笔触颜色    
    	CGContextSetRGBFillColor(context, 0, 1.0, 0, 1);//设置填充色    
    	CGContextSetLineWidth(context, 2.0);//设置线条宽度    
    	CGContextSetLineCap(context, kCGLineCapRound);//设置顶点样式    
    	CGContextSetLineJoin(context, kCGLineJoinRound);//设置连接点样式   
    	/*设置线段样式
    	CGContextSetLineDash(context, phase, lengths, count);    
    	phase:虚线开始的位置 lengths:虚线长度间隔 count:虚线数组元素个数    
    	*/    
    	CGFloat lengths[2] = { 18, 9 };    
    	CGContextSetLineDash(context, 0, lengths, 2);    
    	/*设置阴影
    	CGContextSetShadowWithColor(context, offset, blur, color);    
    	offset:偏移量 blur:模糊度 color:阴影颜色    
    	*/    
    	CGColorRef color = [UIColor grayColor].CGColor;//Quartz2D是跨平台的,使用的是C语言  
    	CGContextSetShadowWithColor(context, CGSizeMake(2, 2), 0.8, color);    
    	//5.绘制图像到指定图形上下文    
    	/*填充方式CGPathDrawingMode   
    	kCGPathFill:只有填充(非零缠绕数填充),不绘制边框    
    	kCGPathEOFill:奇偶规则填充(多条路径交叉时,奇数交叉填充,偶交叉不填充)    
    	kCGPathStroke:只有边框    
    	kCGPathFillStroke:既有边框又有填充    
    	kCGPathEOFillStroke:奇偶填充并绘制边框    
    	*/    
    	CGContextDrawPath(context, kCGPathFillStroke);//最后一个参数是填充类型    
    	//6.释放路径对象    
    	CGPathRelease(path);
    }
    复制代码

    上面的绘制过程太过于麻烦,所以苹果为我们封装了一些绘制方法在UIKit框架中

    - (void)drawRect:(CGRect)rect{    
    	//1.获得图形上下文    
    	CGContextRef context = UIGraphicsGetCurrentContext();    
        //2.添加路径(相当于前面创建路径并添加路径到图形上下文两步操作)    
    	CGContextMoveToPoint(context, 20, 50);    
    	CGContextAddLineToPoint(context, 20, 100);    
    	CGContextAddLineToPoint(context, 300, 100);      
    	//封闭路径:直接调用路径封闭方法    
    	CGContextClosePath(context);    
    	//3.设置图形上下文属性    
    	[[UIColor redColor] setStroke];//设置红色边框    
    	[[UIColor greenColor] setFill];//设置绿色填充    
    	//[[UIColor blueColor] set];//同时设置填充和边框色    
    	//4.绘制路径    
    	CGContextDrawPath(context, kCGPathFillStroke);
    }
    复制代码

    ###二、基本图形的绘图方法

    # 绘制矩形
    CGContextAddRect(CGContextRef context, CGRect rect);
    UIRectFill(CGRect rect);//只有填充
    UIRectFrame(CGRect rect);//只有边框
    # 绘制椭圆
    CGContextAddEllipseInRect(CGContextRef context, CGRect rect);
    # 绘制弧度
    /*
      context:绘制上下文
      x:中心点x坐标
      y:中心点y坐标
      radius:半径
      startAngle:起始弧度,0表示圆的最右边开始
      endAngle:终止弧度,正值表示顺时针计算
      closewise:是否逆时针绘制,0则顺时针绘制
    */
    CGContextAddArc(CGContextRef context, CGFloat x, CGFloat y, 
                  CGFloat radius, CGFloat startAngle, CGFloat endAngle, int closewise);
    # 绘制二次贝塞尔曲线
    /*     
    context:图形上下文     
    cpx:控制点x坐标     
    cpy:控制点y坐标     
    x:结束点x坐标     
    y:结束点y坐标    
    */
    CGContextAddQuadCurveToPoint(CGContextRef context, CGFloat cpx, CGFloat cpy, 
                                 CGFloat x, CGFloat y);
    # 绘制三次贝塞尔曲线
    /*     
    context:图形上下文     
    cp1x:第一个控制点x坐标     
    cp1y:第一个控制点y坐标     
    cp2x:第二个控制点x坐标     
    cp2y:第二个控制点y坐标     
    x:结束点x坐标     
    y:结束点y坐标    
    */
    CGContextAddCurveToPoint(CGContextRef context, CGFloat cp1x, CGFloat cp1y, 
                             CGFloat cp2x, CGFloat cp2y, CGFloat x, CGFloat y);
    复制代码

    ###三、绘制文本和图像

    #pragma mark 绘图
    - (void)drawRect:(CGRect)rect{
        //1.获得图形上下文    
    	CGContextRef context = UIGraphicsGetCurrentContext();
        [self drawText:context];
        [self drawImage:context];
    }
    #pragma mark 绘制文本
    - (void)drawText:(CGContextRef)context{    
    	//绘制到指定的区域内容    
    	NSString *str = @"Star Walk is the most beautiful ......sdadasd dsadsa";
        CGRect rect = CGRectMake(20, 50, 280, 300);    
    	UIFont *font = [UIFont systemFontOfSize:18];//设置字体    
    	UIColor *color = [UIColor redColor];//字体颜色    
    	NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];//段落样式    
    	style.alignment = NSTextAlignmentLeft;//对齐方式    
    	[str drawInRect:rect withAttributes:@{NSFontAttributeName:font,
    							   NSForegroundColorAttributeName:color,
    							   NSParagraphStyleAttributeName:style}];
    }
    #pragma mark 绘制图片
    - (void)drawImage:(CGContextRef)context{    
    	UIImage *image = [UIImage imageNamed:@"image2.jpg"];    
    	//从某一点开始绘制    
    	[image drawAtPoint:CGPointMake(10, 50)];    
    	//绘制到指定的矩形中,注意如果大小不合适会会进行拉伸,图像会形变    
    	[image drawInRect:CGRectMake(10, 50, 300, 450)];    
    	//平铺绘制    
    	[image drawAsPatternInRect:CGRectMake(0, 0, 320, 568)];
    }
    复制代码

    实际上还有一些绘图方法,比如渐变填充叠加模式填充模式,但这些东西使用的不多,这里就不细讲了,有兴趣我可能会另外写个笔记针对这些绘图技巧。 可以参考下面效果:

    ###四、图形上下文形变 Quartz2D的坐标系统UIKit并不一样,它的坐标原点在屏幕左下角,UIKit对其进行了转换,坐标原点统一在屏幕左上角 ######我们也可以对坐标系进行操作:

    #pragma mark 图形上下文形变
    -(void)drawRect:(CGRect rect){
    	CGContextRef context = UIGraphicsGetCurrentContext();	
    	//保存初始状态    
    	CGContextSaveGState(context);    
    	//形变第一步:图形上下文向右平移40    
    	CGContextTranslateCTM(context, 100, 0);    
    	//形变第二步:缩放0.8    
    	CGContextScaleCTM(context, 0.8, 0.8);    
    	//形变第三步:旋转    
    	CGContextRotateCTM(context, M_PI_4/4);    
    	UIImage *image = [UIImage imageNamed:@"photo1.jpg"];    
    	[image drawInRect:CGRectMake(0, 50, 240, 300)];    
    	//恢复到初始状态    
    	CGContextRestoreGState(context);
    }
    复制代码
    • 设置图形上下文形变之前一定要注意保存上下文的初始状态,在使用完之后进行恢复
    • 在iOS开发中不允许开发者直接调用drawRect:方法,刷新绘制内容需要调用setNeedsDisplay方法。

    ###五、其他绘制上下文 ######位图上下文:

    # 开启位图上下文,没有返回值
    UIGraphicsBeginImageContext(CGSize size);
    # 在开启位图上下文和关闭位图上下文之间,使用该方法获取位图上下文
    UIGraphicsGetCurrentContext()
    # 关闭位图上下文,没有返回值
    UIGraphicsEndImageContext()
    复制代码

    ######PDF上下文:

    # 开启PDF上下文,没有返回值
    /*     
    path : 保存路径     
    bounds : pdf文档大小,如果设置为CGRectZero,则使用默认值:612*792     
    pageInfo : 页面设置,为nil则不设置任何信息
    */
    UIGraphicsBeginPDFContextToFile(NSString *path, CGRect bounds, NSDictionary *pageInfo);
    # 在开启PDF上下文和关闭PDF上下文之间,使用该方法获取PDF上下文
    UIGraphicsGetCurrentContext()
    # 关闭PDF上下文,没有返回值
    UIGraphicsEndPDFContext()
    复制代码

    我们怎么知道我们绘制成功了呢? ######对于PDF,我们可以打开看PDF文件 ######对于位图,我们可以把绘制后的位图保存为图片对象UIImage

    # 返回绘制的新图像
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    复制代码

    ######一个PDF绘制的小技巧,就是PDF的分页

    # 开启一个PDF新页,调用了该方法,以后的绘图操作都是在新页上绘制的
    IGraphicsBeginPDFPage()
    复制代码

    凡是“UI”开头的相关绘图函数,都是UIKit对Core Graphics的封装

    转载于:https://juejin.im/post/5b126d88e51d4506af2e7d12

  • 相关阅读:
    二叉树的前中后序遍历(非递归)
    剑指offer——圆圈中最后剩下的数字
    剑指offer——和为s的连续正整数序列
    leetcode300.最长上升子序列
    将网络描述符设置为非阻塞的场景
    leetcode72.编辑距离
    浅谈各种锁机制
    TCP如何保证可靠传输?
    JavaScript(七)
    JavaScript(六)
  • 原文地址:https://www.cnblogs.com/twodog/p/12136763.html
Copyright © 2020-2023  润新知