一、Quartz 2D
Quartz 2D是一个二维图形绘制引擎,支持iOS环境和Mac OS X环境。
Quartz 2D以PDF的规范为基础的图形库,用来绘制二维文字和图形,允许相同的绘图指令在任何装置上,使用可以得到的最佳分辨率,产生相同的输出
Quartz 2D API可以实现许多功能,如基于路径的绘图、透明度、阴影、颜色管理、反锯齿、PDF文档生成和PDF元数据访问等
Quartz 2D API是Core Graphics框架的一部分,因此其中的很多数据类型和方法都是以CG开头的。会经常见到Quartz 2D(Quartz)和Core Graphics两个术语交互使用
Quartz 2D与分辨率和设备无关,因此在使用Quartz 2D绘图时,无需考虑最终绘图的目标设备
二、图形 vs 图像
概念
图形:以路径的方式描述的一个形状,在应用程序运行时,实时绘制(渲染/Rending)的形状
图像:是以二进制数据的形式描述的一块像素点阵,在应用程序运行时,直接将该像素点阵逐一绘制在屏幕上
对比
图像:可以借助第三方工具,如PhotoShop、Adobe Illustrator等预先绘制并以文件的形式保存,能够在应用程序中显示非常炫丽的图片
图形:需要通过代码绘制路径的方式实现,如果要绘制比较华丽的图像,需要非常复杂的算法,但是在绘制简单形状时,其速度和性能要远远高于图像
在应用程序开发时,界面UI上经常会需要使用简单的形状或色块加以点缀。另外,随着iOS 7的扁平化设计理念的普及,原有的拟物化的图片将会被越来越多的图形替代!
为了提高程序的视觉效果及性能,苹果官方建议使用PNG格式的图像
如果是使用AI等矢量软件绘制的图形,在输出图像时,最好针对需要的分辨率重新渲染
三、Core Graphics
Core Graphic框架是一组基于C的API,可以用于一切绘图操作,这个框架的重要性,仅次于UIKit和Foundation
当使用UIKit创建按钮、标签或者其他UIView的子类时,UIKit会用Core Graphics将这些元素绘制在屏幕上。此外,UIEvent(UIKit中的事件处理类)也会使用Core Graphics,用来帮助确定触摸事件在屏幕上所处的位置
因为UIKit依赖于Core Graphics,所以当引入<UIKit/Uikit.h>时,Core Graphics框架会被自动引入,即UIKit内部已经引入了Core Graphics框架的主头文件:<CoreGraphics/CoreGraphics.h>
为了让开发者不必触及底层的Core Graphics的C接口,UIKit内部封装了Core Graphics的一些API,可以快速生成通用的界面元素。但是,有时候直接利用Core Graphics的C接口是很有必要和很有好处的,比如创建一个自定义的界面元素
四、Quartz 2D的几个重要概念
在哪里绘图?
图形上下文(Graphics Context)
如何绘图?
Quartz 2D坐标系
绘图顺序
UIView的drawRect:方法
Quartz 2D的内存管理
五、图形上下文(Graphics Context)
Graphics Context是一个数据类型(CGContextRef),封装了Quartz绘制图像到输出设备的信息。输出设备可以是PDF文件、Bitmap或者显示器的窗口上
Quartz中所有的对象都是绘制到一个Graphics Context中
当用Quartz绘图时,所有设备相关的特性都包含在Graphics Context中。换句话说,我们可以简单地给Quartz绘图序列指定不同的Graphics Context,就可将相同的图像绘制到不同的设备上。而不需要任何设备相关的计算,这些都由Quartz替我们完成
Quartz提供了以下几种类型的Graphics Context:
Bitmap Graphics Context
PDF Graphics Context
Window Graphics Context
Layer Graphics Context
Printer Graphics Context
一个Graphics Context表示一个绘制目标。它包含绘制系统用于完成绘制指令的绘制参数和设备相关信息
Graphics Context定义了基本的绘制属性,如颜色、裁减区域、线条宽度和样式信息、字体信息、混合模式等
在iOS应用程序中,如果要在屏幕上进行绘制,需要创建一个UIView对象,并实现它的drawRect:方法。视图的drawRect:方法在视图显示在屏幕上及它的内容需要更新时被调用
在调用自定义的drawRect:后,视图对象自动配置绘图环境以便能立即执行绘图操作
作为配置的一部分,视图对象将为当前的绘图环境创建一个Graphics Context。通过调用UIGraphicsGetCurrentContext()方法可以获取当前的Graphics Context
六、Quartz 2D坐标系
Quartz中默认的坐标系统是:原点(0, 0)在左下角。沿着X轴从左到右坐标值逐渐增大;沿着Y轴从下到上坐标值逐渐增大
有一些技术在设置它们的graphics context时使用了不同于Quartz的默认坐标系统。最常见的一种修改的坐标系统是原点位于左上角,而沿着Y轴从上到下坐标值逐渐增大。例如:UIView中的UIGraphicsGetCurrentContext方法返回的图形上下文就是用的是这种坐标系
七、UIKit的坐标系
原点(0,0)在屏幕的左上角,X轴向右正向延伸,Y轴向下正向延伸
iOS的像素分辨率会随设备的硬件而变化,iPhone4第一次引入了视网膜屏幕,像素分辨率为960 * 640,刚好是前一代iPod和iPhone像素分辨率( 480 * 320)的两倍
在绘图时,需要使用“点”的概念来思考问题,而不是像素。也就是说在点坐标系中绘图,不是硬件的像素坐标系
虽然这些设备的像素分辨率不同,但用到的坐标系保持不变(以点为单位)。在iPhone4上,一个点会用2像素宽度来绘制
提示:如果绘图的上下文,是使用UIGraphicsGetCurrentContext或者其他以UI开头的方法获取到的,在绘图时无需进行坐标转换
八、Quartz 2D坐标系——坐标系的转换
CGContextRotateCTM(CGContextRef c, CGFloat angle)方法可以相对原点旋转上下文坐标系
CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)方法可以相对原点平移上下文坐标系
CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)方法可以缩放上下文坐标系
注意:
转换坐标系前,使用CGContextSaveGState(CGContextRef c)保存当前上下文状态
坐标系转换后,使用CGContextRestoreGState(CGContextRef c)可以恢复之前保存的上下文状态
九、利用Quartz 2D绘制UIView
当在UIView子类中重写drawRect:方法时,iOS会自动准备好一个图形上下文,可以通过调用UIGraphicsGetCurrentContext()来获取
只要一个UIView需要被刷新或者重绘,drawRect:方法就会被调用,所以drawRect:的调用频率很高
需要注意的是:重绘时应该调用setNeedsDisplay,而不能直接调用drawRect:,setNeedsDisplay会自动调用drawRect:
十、drawRect:注意事项
drawRect:是在UIViewController的loadView和viewDidLoad两方法之后调用的
如果在UIView初始化时没有设置CGRect,drawRect:将不会被自动调用
如果设置UIView的contentMode属性值为UIViewContentModeRedraw,那么将在每次更改frame时自动调用drawRect:
如果使用UIView绘图,只能在drawRect:方法中获取相应的CGContextRef并绘图。而在其他方法中获取的CGContextRef不能用于绘图
十一、Quartz内存管理
使用含有“Create”或“Copy”的函数创建的对象,使用完后必须释放,否则将导致内存泄露
使用不含有“Create”或“Copy”的函数获取的对象,则不需要释放
如果retain了一个对象,不再使用时,需要将其release掉。可以使用Quartz 2D的函数来指定retain和release一个对象。例如,如果创建了一个CGColorSpace对象,则使用函数CGColorSpaceRetain和CGColorSpaceRelease来retain和release对象。也可以使用Core Foundation的CFRetain和CFRelease。注意不能传递NULL值给这些函数
十二、Quartz 2D绘图的基本步骤
1. 获取与视图相关联的上下文对象
UIGraphicsGetCurrentContext
2. 创建及设置路径 (path)
2.1 创建路径
2.2 设置路径起点
2.3 增加路径内容……
3. 将路径添加到上下文
4. 设置上下文属性
边线颜色、填充颜色、线宽、线段连接样式、线段首尾样式、虚线样式…
5. 绘制路径
6. 释放路径
十三、Quartz 2D绘图的基础元素——路径
路径定义了一条或者或多条形状或子路径
子路径可以包含一条或者多条直线或曲线
子路径也可以是一些简单的形状,例如线、圆形、矩形或者星型等
子路径还可以包含复杂的形状,例如地图轮廓或者涂鸦等
路径可以是开放的,也可以是封闭的;对于封闭路径可以空心的也可以是实心的
十四、路径的创建与绘制
路径的创建和绘制是各自独立的任务
可以绘制空心路径、实心路径,或者即绘制路径的边线又填充路径的内容
还可以将路径作为剪切区域,用于将其他对象的绘制约束在路径的区域范围之内
十五、iOS7中预定义的字符属性
NSString *text = @“床前明月光,疑是地上霜";
UIFont *font = [UIFont systemFontOfSize:18];
NSDictionary *dict = @{NSFontAttributeName: font};
CGRect rect = [text boundingRectWithSize:CGSizeMake(24, 1000) options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil];
十六、线性渐变&径向渐变
参数说明:
context: 上下文
gradient: 渐变
startCenter: 渐变开始的起始点坐标
startRadius:渐变开始的起始点半径,如果为0,则从中心点开始发生渐变
endCenter:渐变结束的圆心坐标,一般与起始点坐标相同,也可以略微变化,但是不要变得太远,可以调试看下效果
endRadius: 渐变结束圆的半径
十七、生成添加水印的图像
开始图像上下文
绘制图像
添加水印文字
获取当前图像上下文中的图像结果
结束图像绘制上下文
返回绘制图像
十八、生成PDF文件
1. 创建PDF上下文
2. 新建PDF页面,默认大小612 * 792
3. 结束PDF上下文
注意:
在处理PDF文件时,除了上下文之外,还需要考虑PDF的页面大小