ios基础篇(五)—— Quartz2D

el/2024/6/13 21:36:43

一、Quartz2D

Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac OS X系统(跨平台,纯 C 语言的)。包含在 Core Graphics 框架中。

Quartz 2D能完成的工作

绘制图形 : 线条\三角形\矩形\圆\弧等

  • 绘制文字 微博图片上的水印
  • 绘制\生成图片(图像)
  • 读取\生成PDF
  • 截图\裁剪图片 方型图片->圆型 四个角是透明的
  • 自定义UI控件

注意:

  • Quartz2D 是苹果官方的二维绘图引擎,同时支持 iOS 和 Mac OS X 系统。
  • Cocos2D(Cocos2D-x、Cocos2D-iPhone、Cocos2D-HTML5等), Cocos2D 是一个第三方开源的2D游戏框架。做2D 游戏的 还有 Sprite Kit。 一般3D 游戏用 unity3D。

二、Quartz2D须知

  • Quartz2D的API是纯C语言的
  • Quartz2D的API来自于Core Graphics框架

  • 数据类型和函数基本都以CG作为前缀
  1. CGContextRef
  2. CGPathRef
  3. CGContextStrokePath(ctx);

三、Quartz2D实例

Quartz 2D能做很多强大的事情,例如

裁剪图片

涂鸦\画板

涂鸦\画板

报表:折线图\饼状图\柱状图 (查看 gif 动画图片)

自定义view(自定义UI控件)(通过 Quartz2D绘制自己的控件)

通过继承自 UIView,重写 drawRect:方法实现在控件上绘制各种内容

举例:

  • 通过继承自 UIView 实现自定义的 UIImageView
  • 实现自定义的“下载进度条”控件
  • 幸运转盘控件

四、Quartz2D 绘图主要步骤

  1. 获取【图形上下文】对象
  2. 向【图形上下文】对象中添加【路径】
  3. 渲染(把【图形上下文】中的图形会知道对应的设备上)

【图形上下文】= 草稿纸

  1. 获取草稿纸
  2. 向草稿纸画东西  画的东西约等于路径
  3. 按照草稿纸上的东西 画到自己真实想要画到的地方

五、图形上下文CGContextRef

  • 图形上下文(Graphics Context):是一个CGContextRef类型的数据
  • 图形上下文中主要包含如下信息
  • 绘图路径(各种各样的图形)
  • 绘图状态(颜色、线宽、样式、旋转、缩放、平移、图片裁剪区域等)
  • 输出目标(绘制到什么地方去?UIView、图片、pdf、打印机等) (输出目标可以是PDF文件、Bitmap或者显示器的窗口上)

  • 相同的一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上 不同的上下文的类型,决定你的目标也不一样

Quartz2D提供了以下几种类型的Graphics Context:

  • Bitmap Graphics Context
  • PDF Graphics Context
  • Window Graphics Context
  • Layer Graphics Context(UI控件)
  • Printer Graphics Context

六、使用 Quartz2D 绘图

方式一:直接调用 Quartz2D 的 API 进行绘图

  • 代码量稍大
  • 功能全面
  • 步骤:

1> 获取绘图上下文

2> 把图形绘制到绘图上下文上

3> 把绘图上下文上的图形渲染到对应的设备上

方式二:调用 UIKit 框架封装好的 API 进行绘图

  • 代码相对简单
  • 只对部分 Quartz2D 的 API 做了封装
  • 对于没有封装的功能只能调用 Quartz2D 原生 API
  • 比如:画图片、文字到控件上。(UIKit 已经封装好了)

七、Quartz2D绘图的代码步骤

绘图方式一:

1. 获得图形上下文        C

CGContextRef ctx = UIGraphicsGetCurrentContext(); 

2. 拼接路径(下面代码是搞一条线段)

CGContextMoveToPoint(ctx, 10, 10); //起点
CGContextAddLineToPoint(ctx, 100, 100); //终点
CGContextAddLineToPoint(ctx, 150, 150); //连着的第三条线
//若需从其他起点开始画图 则继续 CGContextMoveToPoint

3. “渲染”(绘制路径)

CGContextStrokePath(ctx); // CGContextFillPath(ctx); 

StrokeXxxx 表示画线(边线)(空心图形)

FillXxx 表示画填充的图形(实心图形)

绘图方式二:

CGPathRef 路径对象   创建一个可变路径对象  C

绘图方式三:

C + OC   oc的path转换为c的path

绘图方式四:

C + OC   c的path转换为oc的path 第一条线用c画 第二条线用OC画

绘图方式五:

纯OC

在渲染时 是会自动获取上下文 并将路径放在上下文当中

 如何把c的转换为OC的      .CGpath

如何把oc的转换为C的 

UIBezierPath  类的 类方法 :bezierPathWithCGPath

七、使用路径对象绘制图形(更简单)

UIBezierPath对象

  • 1. 获取“图形上下文”对象
  • 2. 创建 UIBezierPath 对象
  • 3. 向 UIBezierPath 对象中绘制图形
  • 4. 把 UIBezierPath 对象添加到上下文中
  • 5. 把上下文对象渲染到设备上

注意: UIBezierPath 对象可以独立使用,  无需手动获取“图形上下文”对象

1.代码为什么要写在drawrect当中因为在这个方法当中可以获取到正确的上下文(与上下文有关,先获取当前上下文,上下文是系统创建好的,在其他方法中,可能会获取不到)。2.rect参数的含义当前view的bounds (x y width height)    (rect参数是CGrect类型)3.drawrect 什么时候调用这个方法是系统调用1.当这个view第一次显示的时候会调用2.当这个view进程重绘的时候会调用4.如何重绘1.调用某个需要重绘的 view 对象的 setNeedsDisplay2.调用某个需要重绘的 view 对象的 setNeedsDisplayInRect rect:参数表示需要重绘的区域 (重绘类似于tableview的刷新)5.为什么不能手动调用 drawrect手动调用的时候可能获取不到正确的上下文调setNeedsDisplay 会自动调用drawrect

八、绘图顺序对最终结果的影响

九、在 UIView 上绘图

1. 获取与 UIView 相关的绘图上下文

  • 在drawRect:方法中取得的上下文

  • 在drawRect:方法中取得上下文后,就可以绘制东西到view上

View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,因此,绘制的东西其实是绘制到view的layer上去了

View之所以能显示东西,完全是因为它内部的layer

十、drawRect:方法总结

  • 为什么要实现drawRect:方法才能绘图到view上?

因为在drawRect:方法中才能取得跟view相关联的图形上下文

  • drawRect:方法在什么时候被调用?

当view第一次显示到屏幕上时(加到UIWindow上显示出来)

重绘的时候:调用view的setNeedsDisplay或者setNeedsDisplayInRect:时

  • drawrect 什么时候调用

当 view 第一次被显示的时候调用(调用一次) -

重绘事件被触发的时候, 调用 -

    不要手动去调用这个方法, 否则可能无法正确的获取绘图上下文

  • 如何重绘

手动调用重绘方法 setNeedsDisplay 或者 setNeedsDisplayInRect:

  • rect参数的含义

参数 rect 表示当前 UIView 的 bounds

  • 为什么要在 - (void)drawRect:(CGRect)rect 方法中进行绘图

只有在这个方法中才能获取当前 View 的绘图上下文

十一、通过自定义view来演示案例

如何利用Quartz2D自定义view?(自定义UI控件)

如何利用Quartz2D绘制东西到view上?

  • 首先,得有图形上下文,因为它能保存绘图信息,并且决定着绘制到什么地方去
  • 其次,那个图形上下文必须跟view相关联,才能将内容绘制到view上面

自定义view的步骤

  • 新建一个类,继承自UIView
  • 实现- (void)drawRect:(CGRect)rect方法,然后在这个方法中
  • 取得跟当前view相关联的图形上下文
  • 绘制相应的图形内容
  • 利用图形上下文将绘制的所有内容渲染显示到view上面

十二、绘制基本图形练习 

矩形

圆角矩形:

用圆角矩形画圆:当半径为宽度的一半 正好是圆

当cornerRadius大于50(宽度的一半)的2/3  都是圆

椭圆:

拿椭圆画成圆 将宽和高设置成一样即可

圆 用圆弧的方式画圆

起始位置为0 则为3点钟方向

OC 中:

    

 

C中:

c和oc 画弧线的区别:
相同参数 圆弧方向相反?

c中 顺时针 逆时针的方向相反

圆弧

示例:

换颜色:

c

 oc

可以混用

十三、几种不同的渲染方式

- 空心 StrokePath

- 实心 FillPath 和 EOFillPath (填充)

  • 填充一个路径的时候,路径里面的子路径都是独立填充的。
  • 假如是重叠的路径,决定一个点是否被填充,有两种规则
  • 1,nonzero winding number rule(非零绕数规则),假如一个点被从左到右跨过,计数器+1,从右到左跨过,计数器-1,最后,如果结果是0,那么不填充,如果是非零,那么填充
  • 2,even-odd rule(奇偶规则),假如一个点被跨过1次,被跨过了奇数次,那么要被填充,被跨过偶数次则不填充,和方向没有关系

c: 

oc:

even-odd rule:奇偶填充规则

被覆盖过奇数次的点填充,被覆盖过偶数次的点不填充

nonzero winding number rule:非零绕数规则

默认的填充规则,只需 KCGPathFill即可 从左往右跨过,+1 从右往左跨过 -1 最后如果为0 那么不填充 否则填充

1,表示先绘制的 2,表示后绘制的

两个圆心相同,半径不同的圆

射线 交点  奇数 填充     偶数 不填充

射线圆点的地方填充

addArcWithCenter 画圆弧函数

path.usesEvenOddFillRule = YES;  使用奇偶填充规则

 


http://www.ngui.cc/el/3419349.html

相关文章

ios基础篇(六)—— Quartz2D 饼状图、柱状图

一、绘制“饼状图” 思路: 构建数据,NSArray *data [30, 15, 5, 17, 3, 10, 20];。根据数据个数绘制“扇形”(弧) 注意: 每个弧的起始、结束弧度都是不一样的 每次绘制完毕一个弧以后都要重新设置下一次的起始弧度…

ios基础篇(七)—— 矩阵操作、图形上下文栈、Quartz2D的内存管理、绘制、图片裁剪

一、矩阵操作 - 仿射变换 缩放 void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)旋转 void CGContextRotateCTM(CGContextRef c, CGFloat angle)平移 void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty) #import "HMView.h"impl…

ios基础篇(九)—— 手势识别

UIGestureRecognizer: 手势识别器 能轻松识别用户在某个view上面做的一些常见手势 UIGestureRecognizer 是一个抽象类,定义了所有手势的基本行为,使用它的子类才能处理具体的手势 UIPanGestureRecognizer(拖动) UIPinchGestureRecognizer&a…

ios基础篇(十)—— CALayer基本属性

在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层 在创建UIView对象时,UIView…

ios基础篇(十.一)—— 动画

CADisplayLink CADisplayLink是一种以屏幕刷新频率触发的时钟机制,每秒钟执行大约60次左右 CADisplayLink是一个计时器,可以使绘图代码与视图的刷新频率保持同步,而NSTimer无法确保计时器实际被触发的准确时间 使用方法: 定义…

ios基础篇(十一)—— 同步/异步、进程/线程、pthread、线程状态、线程同步、自动释放池

多线程 一、同步/异步 1、1同步 我们之前写程序的时候都是从上到下,从左到右,代码执行顺序1个人执行多个任务,也是依次执行,1个人同一时间执行1个任务 1.2异步 多个人可以同时执行多个任务 二、进程/线程 2.1进程 进程是指在系统中正在运行的一个应用程序每个…

ios基础篇(十二)—— 消息循环、GCD、任务和队列、串行、并行、Barrier阻塞、延时操作、一次性执行

一、消息循环 什么是消息循环 Runloop就是消息循环,每一个线程内部都有一个消息循环只有主线程的消息循环默认开启,子线程的消息循环默认不开启消息循环的目的 保证程序不退出负责处理输入事件如果没有事件发生,会让程序进入休眠状态 1.1 消…

ios基础篇(十三)—— 调度组、NSOperationQueue

一、调度组 有时候需要在多个异步任务都执行完成之后继续做某些事情,比如下载歌曲,等所有的歌曲都下载完毕之后 转到 主线程提示用户 //1 全局队列dispatch_queue_t queue dispatch_get_global_queue(0, 0);//2 调度组dispatch_group_t group dispatc…

ios基础篇(十五)—— SDWebImage

一、SDWebImage介绍 什么是SDWebImage iOS中著名的牛逼的网络图片处理框架包含的功能:图片下载、图片缓存、下载进度监听、gif处理等等用法极其简单,功能十分强大,大大提高了网络图片的处理效率国内超过90%的iOS项目都有它的影子项目地址 ht…

ios基础篇(十六)—— 网络之sockct

一、网络基本概念 客户端:应用 C/S B/S服务器:为客户端提供服务、数据、资源的机器请求:客户端向服务器索取数据响应:服务器对客户端的请求作出反应,一般是返回给客户端数据服务器 内网服务器外网服务器本地测试服…