Quartz 2D绘图的核心API是CGContextRef,该API专门用于绘制各种图形。
关注微信公众号:ioscoding ,分享优质iOS编程技术。by:shuju
1.1 Quartz 2D绘图基础:CGContextRef
使用Quartz 2D绘图的关键步骤有两步:获取CGContextRef;调用CGContextRef的方法进行绘图。
不同场景下获取CGContextRef的方式各不相同,下面介绍iOS开发中最常见的场景下如何获取CGContextRef。
1. 自定义UIView时获取CGContextRef
开发自定义UIView的方法是,开发一个继承UIView的子类,并重写该UIView的drawRect:方法,当该UIView每次显示出来时,或该UIView的内容需要更新时,系统都会自动调用该UIView的drawRect:方法。在调用drawRect:方法之前,系统会自动配置绘图环境,因此,程序只要通过如下函数即可获取CGContextRef绘图API:
- CGContextRef ctx = UIGraphicsGetCurrentContext();
获取CGContextRef之后,即可进行绘图。
需要指出的是,重写UIView的drawRect:方法绘图时,它的绘图API的坐标原点位于该控件的左上角,横向为X轴,X坐标越大,位置越向右;纵向为Y轴,Y坐标越大,位置越向下。
2. 创建位图时获取CGContextRef
如果需要在创建位图时获取CGContextRef,那么程序需要先调用UIGraphicsBeginImageContext()函数来创建内存中的图片。然后才能调用UIGraphicsGetCurrentContext()获取绘图的CGContextRef。例如如下代码。
- // 创建内存中的图片
- UIGraphicsBeginImageContext(CGSizeMake(320, 480));
- // 获取向内存中图片执行绘图的CGContextRef
- CGContextRef ctx = UIGraphicsGetCurrentContext();
Quartz 2D绘图的核心API是CGContextRef,该API并不是一个对象。由于Quartz 2D本身并不是面向对象的,它是面向过程的API,Quartz 2D提供了大量函数来完成绘图。
Quartz 2D提供的绘图函数如表1.2所示。
表1.2 Quartz 2D的绘图相关函数
函数签名 |
简要说明 |
void CGContextClearRect(CGContextRef c, CGRect rect); |
擦除指定矩形区域上绘制的图形 |
void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode); |
使用指定模式绘制当前CGContextRef中所包 含的路径。第二个参数支持 kCGPathFill、 kCGPathEOFill、kCGPathStroke、kCGPathFillStroke、kCGPathEOFillStroke等枚举值 |
void CGContextEOFillPath(CGContextRef c); |
使用奇偶规则来填充该路径包围的区域。奇 偶规则指:如果某个点被路径包围了奇数次, 系统绘制该点;如果被路径包围了偶数次,系统不绘制该点 |
void CGContextFillPath(CGContextRef c); |
填充该路径包围的区域 |
void CGContextFillRect(CGContextRef c,CGRect rect); |
填充rect代表的矩形 |
void CGContextFillRects(CGContextRef c,const CGRect rects[], size_t count); |
填充多个矩形 |
void CGContextFillEllipseInRect(CGContextRef context, CGRect rect); |
填充rect矩形的内切椭圆区域 |
void CGContextStrokePath(CGContextRef c); |
使用当前 CGContextRef设置的线宽绘制路径 |
void CGContextStrokeRect(CGContextRef c, CGRect rect); |
使用当前 CGContextRef设置的线宽绘制矩形框 |
void CGContextStrokeRectWithWidth(CGContextRef c, CGRect rect, CGFloat width); |
使用指定线宽绘制矩形框 |
void CGContextReplacePathWithStrokedPath(CGContextRef c); |
使用绘制当前路径时覆盖的区域作为当前CGContextRef 中的新路径。举例来说,假如当前CGContextRef包含一 个圆形路径且线宽为10,调用该方法后,当前CGContextRef 将包含一个环宽为10的环形路径 |
void CGContextStrokeEllipseInRect(CGContextRef context,CGRect rect); |
使用当前 CGContextRef设置的线宽绘制rect矩形的内切椭圆 |
void CGContextStrokeLineSegments(CGContextRef c, const CGPoint points[], size_t count); |
使用当前 CGContextRef设置的线宽绘制多条线段。该 方法需要传入2N个CGPoint组成的数组,其中1、2个点 组成第一条线段,3、4个点组成第2条线段,以此类推 |
表12.2中的大部分方法都涉及使用路径,路径由另一个API:CGPathRef来代表。CGPathRef代表任意多条直线或曲线连接而成的任意图形,当CGContextRef根据CGPathRef绘制时,它可以绘制出任意的形状。
关于如何利用CGContextRef来构建路径和添加路径,本节后面会有详细介绍,此处先用最简单的方法来绘制直线、矩形、椭圆等几何形状。
在绘图之前,还需要对绘图的颜色、线条粗细等属性进行设置,Quartz 2D提供了如表12.3所示的函数来设置绘图信息。
表12.3 设置绘图属性的相关函数
方法签名 |
简要说明 |
void CGContextSaveGState(CGContextRef c); |
保存CGContextRef当前的绘图状态,方便以后恢复该状态 |
void CGContextRestoreGState(CGContextRef c); |
把CGContextRef的状态恢复到最近一次保存时的状态 |
CGInterpolationQuality CGContextGetInterpolation Quality(CGContextRef c); |
获取当前CGContextRef在放大图片时的插值质量 |
void CGContextSetInterpolationQuality(CGContextRef c, CGInterpolationQuality quality); |
设置当前CGContextRef在放大图片时的插值质量 |
void CGContextSetLineCap(CGContextRef c, CGLineCap cap); |
设置线段端点的绘制形状。该属性支持如下三个值。 kCGLineCapButt:该属性值指定不绘制端点, 线条结尾处直接结束。这是默认值。 kCGLineCapRound:该属性值指定绘制圆形端点, 线条结尾处绘制一个直径为线条宽度的半圆。 kCGLineCapSquare:该属性值指定绘制方形端点。 线条结尾处绘制半个边长为线条宽度的正方形。需要 说明的是,这种形状的端点与“butt”形状的端点十分相似, 只是采用这种形式的端点的线条略长一点而已 |
void CGContextSetLineDash(CGContextRef c, CGFloat phase, const CGFloat lengths[],size_t count); |
设置绘制边框时所用的点线模式,Quartz 2D支 持非常强大的点线模式。后面会有详细介绍 |
void CGContextSetLineJoin(CGContextRef c, CGLineJoin join); |
设置线条连接点的风格,该属性支持如下三个值: kCGLineJoinMeter:这是默认的属性值。 该方格的连接点形状如所示。 kCGLineJoinRound:该方格的连接点形状如 所示。 kCGLineJoinBevel:该方格的连接点形状如 所示 |
void CGContextSetLineWidth(CGContextRef c, CGFloat width); |
设置绘制直线、边框时的线条宽度 |
void CGContextSetMiterLimit(CGContextRef c, CGFloat limit); |
当把连接点风格设为meter风格时,该方法用于控制锐角箭头的长度 |
void CGContextSetPatternPhase(CGContextRef c, CGSize phase); |
设置该CGContextRef采用位图填充的相位 |
void CGContextSetFillPattern(CGContextRef c, CGPatternRef pattern,const CGFloat components[]); |
设置该CGContextRef使用位图填充 |
void CGContextSetShouldAntialias(CGContextRef c, bool shouldAntialias); |
设置该CGContextRef是否应该抗锯齿(即光滑图形曲线边缘) |
void CGContextSetStrokePattern(CGContextRef c, CGPatternRef pattern, const CGFloat components[]); |
设置该CGContextRef使用位图绘制线条、边框 |
续表
方法签名 |
简要说明 |
||
void CGContextSetBlendMode(CGContextRef context,CGBlendMode mode); |
设置CGContextRef的叠加模式。Quartz 2D 支持多种叠加模式,后面专门有关于叠加模式的介绍 |
||
void CGContextSetAllowsAntialiasing(CGContextRef context, bool allowsAntialiasing); |
设置该CGContextRef是否允许抗锯齿 |
||
void CGContextSetAllowsFontSmoothing(CGContextRef context, bool allowsFontSmoothing); |
设置该CGContextRef是否允许光滑字体 |
||
void CGContextSetShouldSmoothFonts(CGContextRef c,bool shouldSmoothFonts); |
设置该CGContextRef是否允许光滑字体 |
||
void CGContextSetAlpha (CGContextRef c, CGFloat alpha); |
设置全局透明度 |
||
void CGContextSetCMYKFillColor(CGContextRef c, CGFloat cyan, CGFloat magenta, CGFloat yellow,CGFloat black, CGFloat alpha); |
使用CMYK颜色模式来设置该CGContextRef的填充颜色 |
||
void CGContextSetCMYKStrokeColor(CGContextRef c, CGFloat cyan, CGFloat magenta, CGFloat yellow,CGFloat black, CGFloat alpha); |
使用CMYK颜色模式来设置该CGContextRef的线条颜色 |
||
void CGContextSetFillColorWithColor(CGContextRef c, CGColorRef color); |
使用指定颜色来设置该CGContextRef的填充颜色 |
||
void CGContextSetStrokeColorWithColor(CGContextRef c, CGColorRef color); |
使用指定颜色来设置该CGContextRef的线条颜色 |
||
void CGContextSetGrayFillColor(CGContextRef c, CGFloat gray, CGFloat alpha); |
使用灰色来设置该CGContextRef的填充颜色 |
||
void CGContextSetGrayStrokeColor(CGContextRef c, CGFloat gray, CGFloat alpha); |
使用灰色来设置该CGContextRef的线条颜色 |
||
void CGContextSetRGBFillColor(CGContextRef c, CGFloat gray, CGFloat alpha); |
使用RGB颜色模式来设置该CGContextRef的填充颜色 |
||
void CGContextSetRGBStokeColor(CGContextRef c, CGFloat gray, CGFloat alpha); |
使用RGB颜色模式来设置该CGContextRef的线条颜色 |
||
void CGContextSetShadow(CGContextRef context, CGSize offset, CGFloat blur); |
设置阴影在X、Y方向上的偏移,以及模糊度(blur 值越大,阴影越模糊)。该函数没有设置阴影颜色, 默认使用1/3透明的黑色(即RGBA{0, 0, 0, 1.0/3.0})作为阴影颜色 |
||
void CGContextSetShadowWithColor(CGContextRef context, CGSize offset, CGFloat blur, CGColorRef color); |
设置阴影在X、Y方向上的偏移,以及模糊度和阴影的颜色 |