iOS绘图系统(一) UIKit与CoreGraphics

####导语ios

说一下为何写这一系列的文章,笔者以前看到动画就以为头大,被CALayer、Transform等名词弄的晕头转向,也查了许多资料,但大部分的资料都是以一个具体的例子来讲明动画的使用,涉及到不少具体的东西,而对不少基本的概念,动画宏观方面的阐述的比较少,因此想写下这一系列的文章,让初学动画的人有个快速的宏观认识。编程

###一、iOS的绘图系统都有哪些呢?api

iOS主要的绘图系统有UIKit、Core Graphics(也称Quartz 2D)、Core Animation、Core Image、OpenGL ES。每个都主要起什么做用呢?大概介绍一下。性能优化

  • UIKit 最高级的页面,也是你们页面布局常常用到的,好比UIView、UIButton等。能够经过UI前缀来识别UIKit元素。
  • Core Graphics UIKit下的主要绘图系统,用于绘制自定义视图。能够经过CG前缀来识别Core Graphics元素。
  • Core Animation 提供了强大的2D和3D动画。
  • Core Image 对图片进行各类滤镜处理,好比高斯模糊、锐化等。
  • OpenGL ES 主要用于游戏绘图。

###二、视图绘制与视图布局的区别有哪些呢?app

咱们先来理解一下视图绘制周期的概念,这有助于理解视图绘制与视图布局的区别。工具

  • iOS在运行循环(run loop)中整合全部的绘图请求,并一次将它们绘制出来。
  • 不能在主线程中进行复杂的操做,不然会形成主线程的卡顿。
  • 不能在主线程以外的主视图上下文中绘制,只要不是在主视图上下文中绘制,一些UIKit方法是能够在后台线程中使用的。好比能够在任意线程上使用CGBitmapCreateContext建立CGBitmapContext对象并在里面绘图。

视图绘制,是调用UIView中的drawRect方法。若是一个视图调用setNeedsDisplay方法,它就被标记为从新绘制,而且会在下一次绘图周期中从新绘制,也就是会自动调用drawRect方法。oop

视图布局,是调用UIView中的layoutSubviews方法。若是视图中的子视图布局发生变化,须要从新排列,UIKit会自动调用setNeedsLayout方法,也就是对于发生变化的视图逐层次调用layoutSubviews方法。好比frame发生变化、滚动视图等。布局

在画图的时候,咱们应该尽可能避免绘制,多使用布局,这是为何呢?由于布局使用的是GPU(GPU基于硬件进行布局的),而绘制使用的是CPU(基于软件进行绘制的)。性能

补充:CPU VS GPU字体

  1. 关于绘图和动画有两种处理的方式:CPU(中央处理器)和GPU(图形处理器)。在现代iOS设备中,都有能够运行不一样软件的可编程芯片,可是因为历史的缘由,咱们能够说CPU所作的工做都在软件层面,而GPU在硬件层面。
  2. 总的来讲,咱们能够用软件(使用CPU)作任何事情,可是对于图像处理,一般用硬件会更快,由于GPU使用图像对高度并行浮点运算作了优化。因为某些缘由,咱们想尽量把屏幕渲染的工做交给硬件去处理。问题在于GPU并无无限制处理性能,并且一旦资源用完的话,性能就会开始降低了(即便CPU并无彻底占用)
  3. 大多数动画性能优化都是关于智能利用GPU和CPU,使得它们都不会超出负荷。

何时会调用绘制,何时调用布局呢?我本身的理解是这样的,视图在第一次建立的时候,绘制和布局的都会调用的。若是子视图由于一些条件的改变,形成布局的改变,这个时候,系统会自动调用layoutSubviews方法。尽可能避免调用setNeedsDisplay方法。

###三、理解绘图系统中的坐标系

绘图系统中主要使用两种坐标系。

基于点的坐标

原点位于图层的左上角,向右为x轴的正方向,向下为y轴的正方向,一个点的x、y坐标以点为单位。

单位坐标系

原点位于图层的左上角,向右为x轴的正方向,向下为y轴的正方向,一个点的x、y坐标以相对x轴、y轴的比例为值,取值范围为[0, 1]。锚点(anchorPoint)使用单位坐标系。

锚点决定了动画在变化时,z轴的位置。关于锚点的具体做用,坐标变换的具体内容,能够参考下面的两篇文章:

坐标系讲解

坐标变换

###四、管理图形上下文

图形上下文是什么意思呢?好比,咱们要画一幅画,须要有一张画布的,而后在画布上绘制出一幅画来,图形上下文就和画布的概念同样的。在图形上下文中包含了大量信息,好比设置画笔的颜色、设置文本的字体、设置变形等等。

咱们在使用drawRect方法进行绘制的时候,咱们并无建立CGContext,可是咱们却能够画出来本身想要的东西,这是由于,在调用drawRect方法以前,系统为咱们默认建立了一个图形上下文(CGContext)。

咱们在绘图中常常会遇见这几个名词,CGContextSaveGState和CGContextRestoreGState,UIGraphicsPushContext和UIGraphicsPopContext,咱们来分别介绍一下。

[[UIColor redColor] setFill];
    CGContextSaveGState(UIGraphicsGetCurrentContext());
    [[UIColor blackColor] setFill];
    CGContextRestoreGState(UIGraphicsGetCurrentContext());
    UIRectFill(CGRectMake(10, 10, 100, 100));

这段代码设置了画笔的颜色为红色,并保存图形上下文,以后将画笔的颜色改为黑色,并恢复图形上下文。那么最后的画笔颜色是红色仍是黑色的呢?答案是红色的,经过这段代码能看出来CGContextSaveGState和CGContextRestoreGState的用法。

[[UIColor redColor] setFill];
    UIGraphicsPushContext(UIGraphicsGetCurrentContext());
    [[UIColor blackColor] setFill];
    UIGraphicsPopContext();
    UIRectFill(CGRectMake(10, 10, 100, 100));

看下此处的代码,经过运行,咱们发现最后画笔的颜色为黑色,这说明UIGraphicsPushContext并无保存图形上下文的信息,那么它的做用是什么呢?假如你正在图形上下文中绘制什么东西,若是这时想要在位图上下文中绘制彻底不一样的内容,这就是UIGraphicsPushContext的做用了,切换到一个新的位图上。当你在新的位图上,绘制完想要的东西后,在经过UIGraphicsPopContext将刚才的图形上下文出栈,也就是恢复到刚才的绘图状态。

切换到另一个上下文,这是一个比较常见的操做,由于经常使用性,系统api提供了UIGraphicsBeginImageContext的快捷方式,它负责将旧的上下文入栈、为新上下文分配内存、建立新的上下文、翻转坐标系统,并使其做为当前上下文使用。

###五、 透明、不透明、隐藏

视图上有三个比较容易混淆的属性:alpha(透明)、opaque(不透明)和hidden(隐藏)。下面就进行一下深刻的区分。

alpha属性决定了视图会经过像素显示多少信息。alpha为1表示全部的视图信息都在像素上表现出来,而alpha为0表示没有视图信息能在像素上表示出来。

opaque,将视图标记为opaque,即是向绘图系统许诺即将绘制的每个像素都要使用全不透明的颜色,这便容许绘图系统忽略被覆盖在下面的视图,这样能够改善性能,尤为是在进行变形的时候。与opaque紧密相关的是clearsContextBeforeDrawing。它的默认值是YES,会在调用drawRect以前将上下问设置为透明黑底。这样会避免视图中产生的任何垃圾数据。

hidden为YES的话,表示视图根本不会被绘制。

隐藏和透明视图不接受触摸事件,若是想建立一个透明视图而且接受触摸事件,能够这样来进行设置,设置它的alpha为一、opaque为NO且backgroundColor为你活[UIColor clearColor],来接手触摸事件。

###六、 绘图工具神器 下面介绍一款绘图神器(PaintCode) 安装完成后,打开工具,界面以下:

图1-1 paintcode页面

在顶部的菜单栏,提供了一些常见的形状,好比矩形、五角星、多边形。咱们以五角星为例,简单介绍一下其用法。拖动五角星到Canvas上,效果以下:

图1-2所示 绘制五角星

咱们还为其设置了填充颜色为红色的。接下来就是要把作好的图转换成代码导出来,能够在视图下方选择要导出的代码类型,效果以下:

图1-3所示 设置代码导出类型

咱们能够看下导出类的源码是怎么样的,以下图:

图1-4所示 .m文件

该怎么在本身的工程中使用呢?咱们只须要在本身的工程中建立一个UIView,在UIView的drawRect方法,调用其提供的方法便可。以下所示:

图1-5所示 使用范例

至此本文结束了,下一篇将经过两个示例来展现怎么具体使用UIKit与CoreGraphics进行绘制。

参考文章连接:

https://tech.imdada.cn/2016/06/21/ios-core-animation/

http://www.jianshu.com/p/f4096e8dd52e

相关文章
相关标签/搜索