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的封装

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容