iOS中使用CGContext绘制图形

Yeolar   2015-03-25 21:53  

上一篇总结了用 UIBezierPath 绘制图形,本篇讲一下用 CGContextRef 来绘制。CGContext直接在UIGraphics的上下文绘制,也可以把 UIBezierPath 对象的 CGPath 赋值过来。一般在 CAShapeLayer 中使用 UIBezierPath ,而在生成基于矢量图的 UIImageUIView 的绘制时使用CGContext。

CGContext的使用和 UIBezierPath 有些相似,但因为它同时完成绘制而不是只生成路径,所以还包含上下文和绘制部分。

作为对比的话, CAShapeLayer + UIBezierPath 的方式基于矢量路径渲染,利用GPU,而CGContext常用的场景 UIImageUIView 则渲染为位图,性能相对要差。所以在不需要视图级控件的场景,优先考虑 CAShapeLayer

使用CGContext绘制

UIImage 为例,使用CGContext绘制的步骤一般是这样的:

// 1. 准备画板,并支持retina渲染
UIGraphicsBeginImageContextWithOptions(boardSize, NO, 0);

// 2. 取上下文
CGContextRef context = UIGraphicsGetCurrentContext();

// 3. 设置线的属性
CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
CGContextSetLineWidth(context, borderWidth);

// 4. 添加线段
CGContextAddArc(context, center.x, center.y, radius - borderWidth / 2, startAngle, endAngle, 0);

// 5. 绘制
CGContextStrokePath(context);

// 6. 从当前上下文获取图像
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

// 7. 结束当前上下文
UIGraphicsEndImageContext();

return image;

上面绘制了一段弧线,可以选择不同的方法实现不同形状的图像的绘制,也可以选择描边或者填充。

对于 UIView 的子类,可以覆盖 - (void)drawRect:(CGRect)rect 方法,进行绘制。

边缘反锯齿

对于绘制的视图,如果旋转它,会发现有锯齿状的边缘。这是因为iOS出于性能的考虑,默认不开启边缘的反锯齿。

可以使用下面方法开启:

CGContextSetAllowsAntialiasing(context, YES);
CGContextSetShouldAntialias(context, YES);

如果你是直接生成的 UIImage ,然后把它作为视图的背景,则无法使用这种方法。这时有两种办法,一种是在Info.plist中开启全局的边缘反锯齿特性,或者给你的 UIImage 图像增加1px的transparent边,这样可以绕过这个问题。参考 Any quick and dirty anti-aliasing techniques for a rotated UIImageView?

http://www.yeolar.com/note/2015/03/25/ios-cgcontext/

http://www.yeolar.com/note/2015/03/25/ios-cgcontext/