这边从iOS绘图教程 提取一些重要的内容。html
Core Graphics Framework是一套基于C的API框架,使用了Quartz做为绘图引擎。iOS支持两套图形API族:Core Graphics/QuartZ 2D 和OpenGL ES。git
Core Graphics API全部的操做都在一个上下文中进行。因此在绘图以前须要获取该上下文并传入执行渲染的函数中。若是你正在渲染一副在内存中的图片,此时就须要传入图片所属的上下文。得到一个图形上下文是咱们完成绘图任务的第一步,你能够将图形上下文理解为一块画布。若是你没有获得这块画布,那么你就没法完成任何绘图操做。固然,有许多方式得到一个图形上下文,这里我介绍两种最为经常使用的获取方法。github
建立一个图片类型的上下文。调用UIGraphicsBeginImageContextWithOptions
函数就可得到用来处理图片的图形上下文。利用该上下文,你就能够在其上进行绘图,并生成图片。调用UIGraphicsGetImageFromCurrentImageContext
函数可从当前上下文中获取一个UIImage对象。记住在你全部的绘图操做后别忘了调用UIGraphicsEndImageContext
函数关闭图形上下文。框架
利用cocoa为你生成的图形上下文。当你子类化了一个UIView并实现了本身的drawRect:
方法后,一旦drawRect:
方法被调用,Cocoa就会为你建立一个图形上下文,此时你对图形上下文的全部绘图操做都会显示在UIView上。函数
判断一个上下文是否为当前图形上下文须要注意的几点:ui
UIGraphicsBeginImageContextWithOptions
函数不单单是建立了一个适用于图形操做的上下文,而且该上下文也属于当前上下文。drawRect
方法被调用时,UIView的绘图上下文属于当前图形上下文。做为初学者,很容易被UIKit和Core Graphics两个支持绘图的框架迷惑。spa
像UIImage、NSString(绘制文本)、UIBezierPath(绘制形状)、UIColor都知道如何绘制本身。这些类提供了功能有限但使用方便的方法来让咱们完成绘图任务。通常状况下,UIKit就是咱们所须要的。.net
使用UiKit,你只能在当前上下文中绘图,因此若是你当前处于UIGraphicsBeginImageContextWithOptions
函数或drawRect:
方法中,你就能够直接使用UIKit提供的方法进行绘图。若是你持有一个context:参数,那么使用UIKit提供的方法以前,必须将该上下文参数转化为当前上下文。幸运的是,调用UIGraphicsPushContext
函数能够方便的将context:参数转化为当前上下文,记住最后别忘了调用UIGraphicsPopContext函数恢复上下文环境。翻译
这是一个绘图专用的API族,它常常被称为QuartZ或QuartZ 2D。Core Graphics是iOS上全部绘图功能的基石,包括UIKit。code
使用Core Graphics以前须要指定一个用于绘图的图形上下文(CGContextRef),这个图形上下文会在每一个绘图函数中都会被用到。若是你持有一个图形上下文context:参数,那么你等同于有了一个图形上下文,这个上下文也许就是你须要用来绘图的那个。若是你当前处于UIGraphicsBeginImageContextWithOptions
函数或drawRect:
方法中,并无引用一个上下文。为了使用Core Graphics,你能够调用UIGraphicsGetCurrentContext
函数得到当前的图形上下文。
在stackoverflow上,有这样一个问题CGContextSaveGState vs UIGraphicsPushContext问了二者区别,这里列一下高票答案:
UIGraphicsPushContext(context) pushes context onto a stack of CGContextRefs (making context the current drawing context), whereas CGContextSaveGState(context) pushes the current graphics state onto the stack of graphics states maintained by context. You should use UIGraphicsPushContext if you need to make a new CGContextRef the current drawing context, and you should use CGContextSaveGState when you're working with one graphics context and just want to save, for example: the current transform state, fill or stroke colors, etc.
翻译一下就是:
UIGraphicsPushContext(context)
将context压到一个CGContextRefs(使得context成为current context)的栈中。而CGContextSaveGState(context)
将当前绘制状态压到一个context维护的绘制状态的栈中。你可使用UIGraphicsPushContext
当你须要在当前的context去建立一个新的CGContextRef,同时你可使用CGContextSaveGState
当你在处理一个绘制context而且只是想保存的它的时候。好比:当前的变换状态,填充或者线条颜色等。
以上答案其实就是在说:
UIGraphicsPushContext
:压栈当前的绘制对象,生成新的绘制图层CGContextSaveGState
:压栈当前的绘制状态咱们这里用一段实际代码:
-(void)drawRect:(CGRect)rect{ CGContextRef ctx=UIGraphicsGetCurrentContext(); [[UIColor redColor] setStroke]; //红色 CGContextSaveGState(UIGraphicsGetCurrentContext()); CGContextAddEllipseInRect(ctx, CGRectMake(100, 100, 50, 50)); CGContextSetLineWidth(ctx, 10); [[UIColor yellowColor] setStroke]; //黄色 CGContextStrokePath(ctx); CGContextRestoreGState(UIGraphicsGetCurrentContext()); CGContextAddEllipseInRect(ctx, CGRectMake(200, 100, 50, 50)); //红色 CGContextStrokePath(ctx); }
运行一下看结果:
能够看到,CGContextSaveGState
存储下来了当前红色和默认的线条状态,而后切换颜色到黄色和10粗度的线条画圈,而后在CGContextRestoreGState
恢复到了红色和默认的线条状态进行画圈,这个就是存储当前绘制状态的意思。
一样用一段实际代码:
- (void)viewDidLoad { [super viewDidLoad]; CALayer *layer=[CALayer layer]; layer.bounds=CGRectMake(0, 0, 300, 300); layer.position=CGPointMake(100, 100); layer.delegate=self; [layer setNeedsDisplay]; [self.view.layer addSublayer:layer]; } -(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{ UIImage *image = [UIImage imageNamed:@"test.jpg"]; UIGraphicsPushContext(ctx); [image drawInRect:CGRectMake(0, 0, 300, 300)]; UIGraphicsPopContext(); }
运行看一下结果:
若是你将UIGraphicsPushContext(ctx);
与UIGraphicsPopContext();
删去的话,是没法进行绘制的。
缘由是,UIKit的绘制必须在当前的上下文中绘制,而UIGraphicsPushContext能够将当前的参数context转化为能够UIKit绘制的上下文,进行绘制图片。
CGContextSaveGState
是压栈当前的绘制状态,而UIGraphicsPushContext
:压栈当前的绘制对象,生成新的绘制图层。对于UIGraphicsPushContext
的使用,不少都是与UIKit配合使用,更详细的对于CoreGraphics的介绍,能够参考iOS绘图教程 。
1.CGContextSaveGState vs UIGraphicsPushContext
2.iOS --- CoreGraphics中三种绘图context切换方式的区别
3.iOS core graphic使用分析
4.iOS绘图教程 | iOS绘图教程