UIGraphicsGetCurrentContext

CGContextRef

CGContextRef即图形上下文。可以这么理解,我们绘图是需要一个载体或者说输出目标,它用来显示绘图信息,并且决定绘制的东西输出到哪个地方。可以形象的比喻context就像一个“画板”,我们得把图形绘制到这个画板上。所以,绘图必须要先有context

CGContextRef的获取

当你子类化了一个UIView并实现了自己的drawRect:方法后,一旦drawRect:方法被调用,Cocoa就会为你创建一个图形上下文,此时你对图形上下文的所有绘图操作都会显示在UIView上。

CGContextRef使用步骤
  • 先在drawRect方法中获得上下文context
  • 绘制图形(线,图形,图片等)
  • 设置一些修饰属性
  • 渲染到上下文,完成绘图
UIGraphics API介绍
  • 获取上下文
CGContextRef __nullable UIGraphicsGetCurrentContext(void)
  • 矩形填充
void UIRectFill(CGRect rect);

// 填充绘制使用指定的混合模式
void UIRectFillUsingBlendMode(CGRect rect, CGBlendMode blendMode);
  • 矩形描边
void UIRectFrame(CGRect rect);

// 描边绘制使用指定的混合模式
void UIRectFrameUsingBlendMode(CGRect rect, CGBlendMode blendMode);
  • 裁剪
void UIRectClip(CGRect rect);
CGContext API介绍
  • 线宽
void CGContextSetLineWidth(CGContextRef cg_nullable c, CGFloat width)
  • 终点类型
void CGContextSetLineCap(CGContextRef cg_nullable c, CGLineCap cap)
  • 交叉点类型
void CGContextSetLineJoin(CGContextRef cg_nullable c, CGLineJoin join)
  • 透明度
void CGContextSetAlpha(CGContextRef cg_nullable c, CGFloat alpha)
  • 透明矩形区域
void CGContextClearRect(CGContextRef cg_nullable c, CGRect rect)
  • 描边渲染
void CGContextStrokePath(CGContextRef cg_nullable c)
  • 描边颜色
void CGContextSetStrokeColor(CGContextRef cg_nullable c,
    const CGFloat * cg_nullable components)
  • 填充渲染
void CGContextFillPath(CGContextRef cg_nullable c)
  • 填充颜色
void CGContextSetFillColor(CGContextRef cg_nullable c,
    const CGFloat * cg_nullable components)
  • 裁剪
void CGContextClip(CGContextRef cg_nullable c)
  • 闭合路径
void CGContextClosePath(CGContextRef cg_nullable c)
  • 设置阴影
void CGContextSetShadowWithColor(CGContextRef cg_nullable c,
    CGSize offset, CGFloat blur, CGColorRef __nullable color)
  • 设置颜色渐变
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSArray* gradientColors = [NSArray arrayWithObjects:
                               (id)[UIColor whiteColor].CGColor,
                               (id)[UIColor blackColor].CGColor, nil];
CGFloat gradientLocations[] = {0, 1};

CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)gradientColors, gradientLocations);
CGPoint startCenter = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
CGFloat radius = MAX(CGRectGetHeight(rect), CGRectGetWidth(rect));

CGContextDrawRadialGradient(context, gradient, startCenter, 0, startCenter, radius, 0);
  • 设置线性渐变
CGPoint startPoint = CGPointMake(0, 0);
CGPoint endPoint = CGPointMake(200, 200);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
绘制
  • 画线
// 1.获取上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();  
// 2.画线
CGContextMoveToPoint(contextRef, 20, 80); // 起点
CGContextAddLineToPoint(contextRef, self.frame.size.width-20, 80); //终点
// 3.修饰
CGContextSetRGBStrokeColor(contextRef, 0, 1.0, 0, 1.0); // 颜色
CGContextSetLineCap(contextRef, kCGLineCapRound); // 起点和重点圆角
CGContextSetLineJoin(contextRef, kCGLineJoinRound); // 转角圆角
// 4.渲染
CGContextStrokePath(contextRef);
  • 画矩形
/ 1.获取上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();  
// 2.画矩形
CGContextAddRect(contextRef, CGRectMake(50, 50, 100, 100));
// 3.修饰
[[UIColor greenColor] set]; // 颜色
// 4.渲染
CGContextFillPath(contextRef);
  • 画圆
// 1.获取上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();  
// 2.根据矩形画圆(椭圆只是设置不同的长宽)
CGContextAddEllipseInRect(contextRef, CGRectMake(10, 10, 50, 50));
// 3.修饰
[[UIColor greenColor] set]; // 颜色
// 4.渲染
CGContextFillPath(contextRef);
  • 画圆弧
// 1.获取上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();  
// 2.画圆弧
/*
 * 参数一: 上下文
 * 参数二: 中心点x
 * 参数三: 中心点y
 * 参数四: 半径
 * 参数五: 开始弧度
 * 参数六: 结束弧度
 * 参数七: 0为顺时针,1为逆时针
 */
CGContextAddArc(contextRef, 200, 200, 50, M_PI, M_PI_4, 0);
// 3.修饰
[[UIColor greenColor] set]; // 颜色
// 4.渲染
CGContextFillPath(contextRef);
  • 绘制文字
- (void)drawRect:(CGRect)rect {
    //1.获取当前上下文
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //2.创建文字
    NSString *str = @"纸巾艺术";
    //设置字体样式
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    //NSFontAttributeName:字体大小
    dict[NSFontAttributeName] = [UIFont systemFontOfSize:25];
    //字体前景色
    dict[NSForegroundColorAttributeName] = [UIColor blueColor];
    //字体背景色
    dict[NSBackgroundColorAttributeName] = [UIColor redColor];
    //字体阴影
    NSShadow *shadow = [[NSShadow alloc]init];
    //阴影偏移量
    shadow.shadowOffset = CGSizeMake(2, 2);
    //阴影颜色
    shadow.shadowColor = [UIColor greenColor];
    //高斯模糊
    shadow.shadowBlurRadius = 5;
    dict[NSShadowAttributeName] = shadow;
    //字体间距
    dict[NSKernAttributeName] = @10;
    //绘制到上下文
    //从某一点开始绘制 默认 0 0点
    //    [str drawAtPoint:CGPointMake(100, 100) withAttributes:nil];
    //绘制区域设置
    [str drawInRect:rect withAttributes:dict];
    //添加到上下文
    CGContextStrokePath(contextRef);
}
  • 绘制图片
- (void)drawRect:(CGRect)rect {
    //1.获取当前的上下文
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //2.加载图片
    //我们这里只需要加载一次就够了,不需要多次加载,所以不应该保存这个缓存
    UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"222.png" ofType:nil]];
    //绘制一个多大的图片,并且设置他的混合模式以及透明度
    //Rect:大小位置
    //blendModel:混合模式
    //alpha:透明度
    [image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1];
    //添加到上下文
    CGContextFillPath(contextRef);
}
重绘
  • 必须通过调用setNeedsDisplay或者setNeedsDisplayInRect:重绘。
  • 不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕,setNeedsLayout可以重新调用drawRect:方法,实现重绘的功能。
压栈
  • CGContextSaveGState
    压栈当前的绘制状态,当你在处理一个绘制context并且只是想保存的它的时候,CGContextSaveGState(context)将当前绘制状态压到一个context维护的绘制状态的栈中。

  • UIGraphicsPushContext
    压栈当前的绘制对象,生成新的绘制图层,当你需要在当前的context去创建一个新的CGContextRefUIGraphicsPushContext(context)context压到一个CGContextRefs(使得context成为current context)的栈中。

- (void)drawRect:(CGRect)rect {
    CGContextRef purple = UIGraphicsGetCurrentContext();
    // 设置紫色
    [[UIColor purpleColor] setStroke];
    // 设置线宽10
    CGContextSetLineWidth(purple, 10);
    // 画线
    CGContextMoveToPoint(purple, 50, 50);
    CGContextAddLineToPoint(purple, 50, 200);
    
    // 紫色CGContextRef保存到栈
    CGContextSaveGState(purple);
    
    // 重新设置颜色
    [[UIColor redColor] setStroke];
    // 重新设置线宽
    CGContextSetLineWidth(purple, 1);
    
    //把紫色的上下文从栈中取出来
    CGContextRestoreGState(purple);
    // 渲染
    CGContextStrokePath(purple);
}

CGContextSaveGState会保存上下文的信息,线宽、颜色、绘制信息等,取出上下文并使其恢复原样,重新设置并不会生效。

效果:紫色线,宽度10

- (void)drawRect:(CGRect)rect {
    CGContextRef purple = UIGraphicsGetCurrentContext();
    // 设置紫色
    [[UIColor purpleColor] setStroke];
    // 设置线宽10
    CGContextSetLineWidth(purple, 10);
    // 画线
    CGContextMoveToPoint(purple, 50, 50);
    CGContextAddLineToPoint(purple, 50, 200);
    
    // 紫色CGContextRef保存到栈
    UIGraphicsPushContext(purple);
    
    // 重新设置颜色
    [[UIColor redColor] setStroke];
    // 重新设置线宽
    CGContextSetLineWidth(purple, 1);
    
    //把紫色的上下文从栈中取出来
    UIGraphicsPopContext();
    // 渲染
    CGContextStrokePath(purple);
}

UIGraphicsPushContext会保存上下文的信息,线宽、颜色、绘制信息等,取出的是一个全新的绘图上下文,重新设置会生效。

效果:红色线,宽度1

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

推荐阅读更多精彩内容