本篇DEMO
在iOS中进行绘图,不管你是否了解,基本上就是使用的Core Graphics。Core Graphics Framework是一套基于C的API框架,使用了Quartz作为绘图引擎。它提供了低阶别、轻量级、高保真度的2D渲染,该框架可以用于基于路径的绘图、变换、颜色管理、脱屏渲染、模板、渐变、遮蔽、图像数据处理、图像的创建、遮罩、以及PDF文档的创建、显示和分析。
Core Graphics API的所有操作都是在一个上下文中进行。所以在绘图之前,我们需要去获取该上下文,并传入执行渲染的函数中。
- 获取上下文的几种方式
//创建图片类型的上下文
UIGraphicsBeginImageContextWithOptions
//UIView,在drawRect中,Cocoa会为你创建一个图形上下文
- (void)drawRect:(CGRect)rect
//CALayer
- (void)drawInContext:(CGContextRef)ctx
//delegate回调
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
- UIGraphicsBeginImageContextWithOptions函数创建的上下文适用于图像操作,并且该上下文属于当前上下文,你也可以通过UIGraphicsGetCurrentContext函数获得当前图形上下文
- drawRect方法调用时,Cocoa创建的上线属于当前图形上下文,你也可以通过UIGraphicsGetCurrentContext函数获得当前图形上下文
- delegate回调所持有的context,只是对一个图形上下文的引用,并不一定是当前上下文
绘图框架
UIKit
像UIImage、NSString、UIBezierPath、UIColor都提供了方法帮助我们完成绘图任务,虽然功能有限,但大多数情况下都能满足我们的需求
Core Graphics
这是一个绘图专用的API族,通常也被成为QuartZ 2D。Core Graphics是iOS上所有绘图功能的基石,包括UIKit。
下面我们通过栗子来介绍几种不同的绘图方法
UIKit:在UIView的子类方法drawRect方法中进行绘图
- (void)drawRect:(CGRect)rect {
//绘制一个空心圆
UIBezierPath *round = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.bounds.size.width/2];
[[UIColor redColor] setStroke];
[round stroke];
}
Core Graphics:在drwaRect中实现绘制
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// CGMutablePathRef path = CGPathCreateMutable();
// CGPathAddRoundedRect(path, nil, self.bounds, self.bounds.size.width/2, self.bounds.size.width/2);
// CGPathCloseSubpath(path);
// CGContextAddPath(context, path);
CGContextAddEllipseInRect(context, self.bounds);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetLineWidth(context, 10);
// CGContextClip(context);
CGContextStrokePath(context);
}
在代理回调方法中进行绘制
- 需要注意的是设置CALayer对象的代理时,不要将UIView对象设置为显示层的委托对象,这是因为UIView对象已经是隐式层的代理对象,再将它设置为两一个层的委托对象就会出现问题。你可以编写一个负责绘制图形的代理类。如果你不小心设置了代理为view,最好在dealloc方法中将layer对象的代理置空。至于绘图的方法基本就和上边的类似。
UIGraphicsBeginImageContextWithOptions
- (void)drawRect:(CGRect)rect {
//UIKit
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0);
//UIKit
// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.bounds.size.width/2];
// [[UIColor redColor] setStroke];
// [path stroke];
//Core Graphics
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(ctx, self.bounds);
CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
CGContextSetLineWidth(ctx, 1);
CGContextStrokePath(ctx);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *imageV = [[UIImageView alloc] initWithFrame:self.bounds];
[imageV setImage:image];
[self addSubview:imageV];
}
CAShapeLayer绘图,可以快速实现一些简单的动画
- (void)drawRect:(CGRect)rect {
CAShapeLayer *layer = [CAShapeLayer layer];
layer.strokeColor = [UIColor redColor].CGColor;
layer.fillColor = [UIColor clearColor].CGColor;
layer.lineWidth = 2;
layer.lineCap = kCALineCapRound;
[self.layer addSublayer:layer];
//UIKit
// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.bounds.size.width/2];
// layer.path = path.CGPath;
//Core Graphics
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRoundedRect(path, nil, self.bounds, self.bounds.size.width/2, self.bounds.size.height/2);
CGPathCloseSubpath(path);
layer.path = path;
CGPathRelease(path);
}
- 这些只是绘图的一些简单使用,后续会结合demo实现一些复杂的绘图。