iOS绘图
2018-11-08 本文已影响9人
cxlhaha
前言
当遇到绘图需求的时候我们就需要利用UIKit或者是CoreGraphics这两个绘图框架进行绘图,而这两个框架之间的关系是这样的:
-
CoreGraphics是绘图方面的基础,它提供了大量的API满足我们各种各样的绘图需求,但是,因为CoreGraphics更加底层,是一套C语言的框架,所以,UIKit帮我们进行了封装,我们可以利用UIKit简洁的语法,快速的实现绝大多数的绘图需求。所以当绘图需求简单,我们想要快速实现时,我们可以利用UIKit进行绘图,而如果需要全部功能的绘图需求,我们就选择功能强大的CoreGraphics进行绘图。
-
UIKit只能在当前上下文中进行绘图,如果不是当前上下文需要转化为当前上下文再进行绘图。
如何绘图
因为我们需要在图形上下文上进行绘图,这里有两种常用的获取图形上下文的方式:
方式一:创建图片类型上下文
- UIKit实现:
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
[[UIColor greenColor] set];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 200, 200)];
[path fill];
UIImageView *imgView = [[UIImageView alloc]initWithImage:UIGraphicsGetImageFromCurrentImageContext()];
imgView.frame = CGRectMake(100, 100, 200, 200);
[self.view addSubview:imgView];
UIGraphicsEndImageContext();
- CoreGraphics实现:
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
CGContextRef con = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(con, CGRectMake(0, 0, 200, 200));
CGContextSetFillColorWithColor(con, [UIColor greenColor].CGColor);
CGContextFillPath(con);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIImageView *imgView = [[UIImageView alloc]initWithImage:img];
imgView.frame = CGRectMake(0, 0, 200, 200);
[self.view addSubview:imgView];
UIGraphicsEndImageContext();
方式二:drawRect:方法获取图形上下文
- UIKit实现:
-(void)drawRect:(CGRect)rect
{
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 200, 200)];
[path fill];
}
- CoreGraphics实现:
-(void)drawRect:(CGRect)rect
{
CGContextRef con = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(con, CGRectMake(0, 0, 200, 200));
CGContextFillPath(con);
}
性能问题
值得注意的是,当我们进行绘图的时候,有时候会出现性能问题。
比如说:当我们要实现一个画板功能时,我们首先想到的是重写drawRect方法,进行绘图,但是当画板足够大时,我们会发现,绘图时内存会暴增。这是因为,调用drawRect方法时,会生成系统会生成寄宿图,渲染前都会保存这张图片,当画板足够大时,就会导致内存暴增。当然有一些方法可以优化,我这里就不展开分析,我要说的是,最好的优化就是不去绘图,比如,那个画板需求,我们可以用CAShapeLayer实现,我们就会发现性能稳定多了,下面我就把两种实现的代码贴出来,有兴趣的同学自己尝试一下就会发现差别。
drawRect:
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
CGPoint point = [touches.anyObject locationInView:self];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:point];
[self.pathArray addObject:path];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
CGPoint point = [touches.anyObject locationInView:self];
UIBezierPath *path = self.pathArray.lastObject;
[path addLineToPoint:point];
[self setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect
{
for (UIBezierPath *path in self.pathArray) {
[path stroke];
}
}
CAShapeLayer:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
CGPoint point = [touches.anyObject locationInView:self];
UIBezierPath *path = [UIBezierPath bezierPath];
path.lineWidth = 5;
[path moveToPoint:point];
self.lastPath = path;
CAShapeLayer *sLayer = [CAShapeLayer layer];
sLayer.strokeColor = [UIColor blackColor].CGColor;
sLayer.fillColor = [UIColor clearColor].CGColor;
[self.layer addSublayer:sLayer];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
CGPoint point = [touches.anyObject locationInView:self];
[self.lastPath addLineToPoint:point];
CAShapeLayer *slayer= self.layer.sublayers.lastObject;
slayer.path = self.lastPath.CGPath;
}
其它内容的绘图
- 文字绘制
NSString *str = @"fdfas";
[str drawInRect:CGRectMake(100, 100, 100, 100) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15],NSForegroundColorAttributeName:[UIColor greenColor]}];
- 图像绘制
UIImage *image = [UIImage imageNamed:@"121"];
[image drawInRect:CGRectMake(0, 0, 100, 100)];