绘图-Core Graphics

前言

CGContext又叫图形上下文,相当于一块画布,以堆栈形式存放,只有在当前context上绘图才有效。iOS有分多种图形上下文,其中UIView自带提供的在drawRect:方法中通过UIGraphicsGetCurrentContext获取,还有专门为图片处理的context,UIGraphicsBeginImageContext函数生成,还有pdf的context等等。

Core Graphics Framework是一套基于C的API框架,使用了Quartz作为绘图引擎。iOS支持两套图形API族:Core Graphics/QuartZ 2D 和OpenGL ES。前者提供了低级别、轻量级、高保真度的2D渲染。该框架可以用于基于路径的绘图、变换、颜色管理、脱屏渲染,模板、渐变、遮蔽、图像数据管理、图像的创建、遮罩以及PDF文档的创建、显示和分析。

Quart 2D 是一组二位绘图和渲染API,Core Graphic会使用到这组API

这是一个绘图专用的API族,它经常被称为QuartZ或QuartZ 2D。Core Graphics是iOS上所有绘图功能的基石,包括UIKit。

顺便说一下,有代码工具 PaintCode 可以生成相应的 Core Graphics 代码,直接拖进工程中就可以使用,可以大幅加快开发进程,当然是你先学会使用PaintCode才行

简述

绘图的步骤:(在drawRect函数中)
1.获取绘图上下文
2.创建并设置路径
3.将路径添加到上下文
4.设置上下文状态
5.绘制路径
6.释放路径

在使用Core Graphics 时有许多方式获得一个图形上下文,这里我介绍两种最为常用的获取方法
第一种方法就是创建一个图片类型的上下文。
调用UIGraphicsBeginImageContextWithOptions函数就可获得用来处理图片的图形上下文。利用该上下文,你就可以在其上进行绘图,并生成图片。
调用UIGraphicsGetImageFromCurrentImageContext函数可从当前上下文中获取一个UIImage对象。记住在你所有的绘图操作后别忘了调用UIGraphicsEndImageContext函数关闭图形上下文。

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

Core Graphics 里面的类文件众多:


Paste_Image.png

让我们来看一下CGContext.h 里面的方法:

CGContextRef context = UIGraphicsGetCurrentContext(); 设置上下文                
CGContextMoveToPoint 开始画线
CGContextAddLineToPoint 画直线

CGContextAddEllipseInRect 画一椭圆
CGContextSetLineCap 设置线条终点形状        #三个枚举值
#1.kCGLineCapButt该属性值指定不绘制端点, 线条结尾处直接结束。这是默认值。
#2.kCGLineCapRound该属性值指定绘制圆形端点, 线条结尾处绘制一个直径为线条宽度的半圆
#3.kCGLineCapSquare该属性值指定绘制方形端点。线条结尾处绘制半个边长为线条宽度的正方形。需要说明的是,
#这种形状的端点与“butt”形状的端点十分相似,只是采用这种形式的端点的线条略长一点而已
CGContextSetLineDash 画虚线
CGContextAddRect 画一方框
CGContextStrokeRect 指定矩形
CGContextStrokeRectWithWidth 指定矩形线宽度
CGContextStrokeLineSegments 一些直线


CGContextAddArc 画已曲线 前俩店为中心 中间俩店为起始弧度 最后一数据为0则顺时针画 1则逆时针
CGContextAddArcToPoint(context,0,0, 2, 9, 40);//先画俩条线从point 到 弟1点 , 从弟1点到弟2点的线  切割里面的圆   
CGContextSetShadowWithColor 设置阴影   
CGContextSetRGBFillColor 这只填充颜色
CGContextSetRGBStrokeColor 画笔颜色设置    
CGContextSetFillColorSpace 颜色空间填充   
CGConextSetStrokeColorSpace 颜色空间画笔设置
CGContextFillRect 补充当前填充颜色的rect
CGContextSetAlaha 透明度


CGContextTranslateCTM 改变画布位置
CGContextSetLineWidth 设置线的宽度
CGContextAddRects 画多个线
CGContextAddQuadCurveToPoint 画曲线
CGContextStrokePath 开始绘制图片
CGContextDrawPath 设置绘制模式
CGContextClosePath 封闭当前线路
CGContextTranslateCTM(context, 0, rect.size.height);    
CGContextScaleCTM(context, 1.0, -1.0);反转画布      
CGContextSetInterpolationQuality 背景内置颜色质量等级 
CGImageCreateWithImageInRect 从原图片中取小图


字符串的 写入可用  nsstring本身的画图方法 
- (CGSize)drawInRect:  (CGRect)rect withFont:(UIFont *)font lineBreakMode:
(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment;来写进去即可

对图片放大缩小的功能就是慢了点  
UIGraphicsBeginImageContext(newSize);    
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();  
UIGraphicsEndImageContext();


CGColorGetComponents() 返回颜色的各个直 以及透明度 可用只读const float 来接收  是个数组


画图片 
CGImageRef image= CGImageRetain(img.CGImage);   
CGContextDrawImage(context, CGRectMake(10.0, height -100.0, 90.0, 90.0), image);


 实现逐变颜色填充方法
 CGContextClip(context);   
 CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();   
 CGFloat colors[] =    {  204.0 / 255.0, 224.0 / 255.0, 244.0 /  255.0, 1.00,       
     29.0 / 255.0, 156.0 / 255.0, 215.0 / 255.0, 1.00, 0.0 /     
     255.0,  50.0 / 255.0, 126.0 / 255.0, 1.00,    
  };  
 CGGradientRef gradient =CGGradientCreateWithColorComponents (rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4));   
 CGColorSpaceRelease(rgb);             
 CGContextDrawLinearGradient(context,gradient,CGPointMake(0.0,0.0),CGPointMake(0.0,self.frame.size.height), kCGGradientDrawsBeforeStartLocation);

 **注意释放掉对象,已释放内存**
 注:  画完图后,必须    
 先用CGContextStrokePath来描线,即形状    
 后用CGContextFillPath来填充形状内的颜色.


 填充一个路径的时候,路径里面的子路径都是独立填充的。
 假如是重叠的路径,决定一个点是否被填充,有两种规则
 1,nonzero winding number rule:非零绕数规则,假如一个点被从左到右跨过,计数器+1,从右到左跨过,计数器-1,最后,如果结果是0,那么不填充,如果是非零,那么填充。
 2,even-odd rule: 奇偶规则,假如一个点被跨过,那么+1,最后是奇数,那么要被填充,偶数则不填充,和方向没有关系。


Function
Description  
CGContextEOFillPath 使用奇偶规则填充当前路径     
CGContextFillPath 使用非零绕数规则填充当前路径
CGContextFillRect 填充指定的矩形 
CGContextFillRects 填充指定的一些矩形 
CGContextFillEllipseInRect 填充指定矩形中的椭圆 
CGContextDrawPath 两个参数决定填充规则,kCGPathFill表示用非零绕数规则,kCGPathEOFill表示用奇偶规则,kCGPathFillStroke表示填充, kCGPathEOFillStroke表示描线,不是填充


设置当一个颜色覆盖上另外一个颜色,两个颜色怎么混合
默认方式是   
result = (alpha * foreground) + (1 - alpha) * background
CGContextSetBlendMode :设置blend mode.
CGContextSaveGState :保存blend mode.
CGContextRestoreGState:在没有保存之前,用这个函数还原blend mode.
CGContextSetBlendMode 混合俩种颜色

让我们来看一下CGPath.h 里面的方法:

Paste_Image.png

Creating and Managing Paths

CGPathCreateMutable  创建一个可变的图形路径。
CGPathCreateWithEllipseInRect   创建一个椭圆的不可变路径。
CGPathCreateWithRect    创建一个矩形的不可变路径。
CGPathCreateWithRoundedRect 创建一个圆角矩形的不可变路径。
CGPathCreateCopy    创建一个图形路径的不可变副本。
CGPathCreateCopyByTransformingPath  创建由变换矩阵变换的图形路径的不可变副本。
CGPathCreateCopyByDashingPath  创建另一个路径的虚线副本。
CGPathCreateCopyByStrokingPath   创建另一个路径的实线副本。
CGPathCreateMutableCopy    创建一个现有的图形路径可复制。
CGPathCreateMutableCopyByTransformingPath  创建一个图形路径的变换矩阵将可变副本。
CGPathRelease      减少图形路径
CGPathRetain        递增一个图形路径的保留计数。

Modifying Quartz Paths

CGPathAddArc   追加一个弧一个可变的图形路径,可能前面的直线段。
CGPathAddRelativeArc   追加一个弧一个可变的图形路径,可能前面的直线段。
CGPathAddArcToPoint  追加一个弧一个可变的图形路径,可能前面的直线段。
CGPathAddCurveToPoint  //绘制三次贝塞尔曲线
CGPathAddLines  追加新的线段图形路径数组的一个可变的。
CGPathAddLineToPoint   追加一条线段一个可变的图形路径。
CGPathAddPath   添加一个路径到一个可变的图形路径。
CGPathAddQuadCurveToPoint   //绘制二次贝塞尔曲线

CGPathAddRect   添加一个矩形,一个可变的图形路径。
CGPathAddRects  追加矩形可变图形路径数组。
CGPathAddRoundedRect   添加一个圆角矩形可变图形路径。
CGPathApply   每个元素的图形路径中,调用一个自定义应用功能。
CGPathMoveToPoint   开始在一个可变的图形路径指定一个位置,一个新的子路径。
CGPathCloseSubpath   关闭和一个可变的图形路径完成子路径。
CGPathAddEllipseInRect   添加一个路径,一个适合矩形内的椭圆。

Getting Information about Quartz Paths

CGPathEqualToPath  指示是否两个图形路径是等效的。
CGPathGetBoundingBox  返回包含在图形路径中的所有点的包围盒。
CGPathGetPathBoundingBox   返回图形路径的包围盒
CGPathGetCurrentPoint   返回图形路径中的当前点。
CGPathGetTypeID   返回用于石英图形路径的核心基础类型标识符。
CGPathIsRect     指出是否代表一个矩形图形路径。
CGPathContainsPoint  检查一个点是否包含在图形路径中。
CGLineCap   用于渲染一个行的端点的样式。
CGLineJoin   用于线的连接类型。

苹果官CGPath

CGRectGet系列

CGRectInset(CGRect rect, CGFloat dx, CGFloat dy) dx,dy 是在rect的内部左右,上下距离的值。
CGRectGetHeight返回label本身的高度 
CGRectGetMinY返回label顶部的坐标 
CGRectGetMaxY 返回label底部的坐标
CGRectGetMinX 返回label左边缘的坐标 
CGRectGetMaxX 返回label右边缘的坐标 
CGRectGetMidX表示得到一个frame中心点的X坐标 
CGRectGetMidY表示得到一个frame中心点的Y坐标

根据颜色绘制图片

  -(UIImage *)imageFromColor:(UIColor*)color
  {
    CGRect rect = CGRectMake(0, 0, 1, 1);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context,[color CGColor]);
    CGContextFillRect(context, rect);
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

值得注意的一点是:

CGContextSaveGState(context);和CGContextRestoreGState(context);
这一对方法的作用是,前者的调用,将会把当前的上下文状态保存在一个“绘图状态栈”中,后者的作用是,将上一次保存在栈中的上下文状态取出,作为当前的上下文状态。这样做的目的,是因为对上下文进行变换会改变上下文整体坐标系,如果在变换上下文前,不进行保存,之后也不恢复的话,再在此上下文绘图,就会按照新的变化后的坐标系绘图,从而发生混乱。

小结

CGContextRefCGMutablePathRef 都是画图工具,但是

  • CGContextRef 可以自己展示出图形
  • CGMutablePathRef 需要与CAShapeLayerCGContextRef配合使用后才可以展示出图形,它只是负责绘制路径path的.

推荐好文章:
打造自己的“美图秀秀”
关于Core Image 看这里


效果.gif

本文考虑到简洁就不上代码了,具体的代码实现的效果可以到我GitHub去下载查看,喜欢的话,请star 一下。

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

推荐阅读更多精彩内容