CoreGraphics系列学习(一)

6,068 阅读4分钟

前言

最近换了份新工作要使用到CoreGraphics去绘图,作者对这个框架不是很熟悉就决定开始研究一下这个框架

Core Graphics是Quartz 2D的一个高级绘图引擎,常用与iOS,tvOS,macOS的图形绘制应用开发。Core Graphics是对底层C语言的一个简单封装,其中提供大量的低层次,轻量级的2D渲染API。

Core Graphics在绘图系统中的地位

我们最常用的绘图框架就是UIKit,其底层是CoreGraphics实现的,而且绝大多数的图形界面也都是由UIKit完成。

Core Graphics在绘图系统中的结构图:

  • UIKit:最常用的视图框架,封装度最高,都是OC对象
  • CoreGraphics:主要绘图系统,常用于绘制自定义视图,纯C的API,使用Quartz2D做引擎
  • CoreAnimation:提供强大的2D和3D动画效果
  • OpenGL-ES:主要用于游戏绘制,但它是一套编程规范,具体由设备制造商实现

Core Graphics的坐标系

UIKit的坐标与Core Graphics的坐标是不一样的,UIKit的坐标默认原点在左上角,而Core Graphics的原点在左下角

通常两个坐标系之间是需要转换的,左图是修改前,右图是修改后:

那为什么我们在drawRect方法中使用CoreGraphics方法绘制内容的时候可以使用UIKit的坐标系?
因为iOS系统在drawRect返回CGContext的时候,默认帮我们进行了一次变换,以方便开发者直接用UIKit坐标系进行渲染。

转换坐标的API

/*
平移坐标系统。该方法相当于把原来位于 (0, 0) 位置的坐标原点平移到 (tx, ty) 点。
在平移后的坐标系统上绘制图形时,所有坐标点的 X 坐标都相当于增加了 tx,
所有点的 Y 坐标都相当于增加了 ty。
*/
CGContextTranslateCTM(CGContextRef  _Nullable c, CGFloat tx, CGFloat ty)

/*
缩放坐标系统。该方法控制坐标系统水平方向上缩放 sx,垂直方向上缩放 sy。
在缩放后的坐标系统上绘制图形时,所有点的 X 坐标都相当于乘以 sx 因子,
所有点的 Y 坐标都相当于乘以 sy 因子。
*/
CGContextScaleCTM(CGContextRef  _Nullable c, CGFloat sx, CGFloat sy)

/*
旋转坐标系统。该方法控制坐标系统旋转 angle 弧度。
在缩放后的坐标系统上绘制图形时,所有坐标点的 X、Y 坐标都相当于旋转了 angle弧度之后的坐标。
*/
CGContextRotateCTM(CGContextRef  _Nullable c, CGFloat angle)

图形上下文Graphics Context

图形上下文(CGContext)对于我们来说是一个透明的东西,我们不需要关心它的实现以及它是怎么绘制的,只需把我们要绘制的内容告诉它即可。

Core Graphics中提供如下几种图形上下文:
位图图形上下文(Bitmap Graphics Context):位图图形上下文用于将RGB图像,GMYK图像或者黑白图像绘制到一个位图(bitmap)对象中。
PDF图形上下文(PDF Graphics Context):PDF图形上下文可以帮助开发者创建PDF文件,将内容绘制进PDF文件中,其与位图上下文最大的区别在于PDF数据可以保存多页图像。
窗口上下文(Window Graphics Context):用于OS系统中的窗口绘制。
图层上下文(Layer Context):用于将内容绘制在Layer图层上。
打印上下文(Post Graphics Context):使用Mac打印功能时,此上下文用于将内容绘制在打印输出源上。

而在iOS开发中,视图显示在屏幕上及它的内容需要更新时会被调用drawRect:方法。我们只需要实现drawRect:方法,并且把我们需要绘制的内容提供给获取到的上下文就可以实现绘制。

获取当前上下文

- (void)drawRect:(CGRect)rect {
	// 获取当前上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    ...
}

设置绘图的上下文(context)

  • UIGraphicsPushContext(context):把context压入栈中,并把context设置为当前绘图上下文
  • UIGraphicsPopContext():将栈顶的上下文弹出,恢复先前的上下文,但是绘图状态不变
- (void)drawRect:(CGRect)rect {
  [[UIColor redColor] setFill];
  UIGraphicsPushContext(UIGraphicsGetCurrentContext());
  [[UIColor blackColor] setFill];
  UIGraphicsPopContext();
  UIRectFill(CGRectMake(100, 100, 100, 100)); // black color
}

设置绘图的状态(state)

  • CGContextSaveGState(context):保存context的状态
  • CGContextRestoreGState:恢复保存context的状态
- (void)drawRect:(CGRect)rect {
  [[UIColor redColor] setFill];
  CGContextSaveGState(UIGraphicsGetCurrentContext());
  [[UIColor blackColor] setFill];
  CGContextRestoreGState(UIGraphicsGetCurrentContext());
  UIRectFill(CGRectMake(100, 100, 100, 100)); // red color
}

参考文章

Core Graphics的简介与概述(一)

iOS绘图框架CoreGraphics分析