iOS开发UI篇—Quartz2D使用(图形上下文栈)

一、qurza2d是怎么将绘图信息和绘图的属性绘制到图形上下文中去的?

说明:

新建一个项目,自定义一个view类和storyboard关联后,重写该类中的drowrect方法。

画线的三个步骤:

(1)获取上下文

(2)绘图

(3)渲染

要求:画两条单独的线

代码和效果图:

 1 - (void)drawRect:(CGRect)rect
 2 {
 3 //获取上下文  4 CGContextRef ctx=UIGraphicsGetCurrentContext();
 5 //绘图
 6 //第一条线  7 CGContextMoveToPoint(ctx, 20, 100);
 8 CGContextAddLineToPoint(ctx, 100, 320);
 9 10 //第二条线 11 CGContextMoveToPoint(ctx, 40, 200);
12 CGContextAddLineToPoint(ctx, 80, 100);
13 //渲染 14  CGContextStrokePath(ctx);
15 16 }


效果图:


设置线段的宽度:两头为圆形,颜色等。

代码和效果图(发现第二条线也被渲染成第一条线的样式和状态)

 1 - (void)drawRect:(CGRect)rect
 2 {
 3 //获取上下文  4 CGContextRef ctx=UIGraphicsGetCurrentContext();
 5 //绘图
 6 //第一条线  7 CGContextMoveToPoint(ctx, 20, 100);
 8 CGContextAddLineToPoint(ctx, 100, 320);
 9 10 //设置第一条线的状态
11 //设置线条的宽度 12 CGContextSetLineWidth(ctx, 12);
13 //设置线条的颜色 14 [[UIColor brownColor]set];
15 //设置线条两端的样式为圆角 16  CGContextSetLineCap(ctx,kCGLineCapRound);
17 //对线条进行渲染 18  CGContextStrokePath(ctx);
19 20 //第二条线 21 CGContextMoveToPoint(ctx, 40, 200);
22 CGContextAddLineToPoint(ctx, 80, 100);
23 //渲染 24  CGContextStrokePath(ctx);
25 26 }


效果图:


新的需求:要让两条线的颜色不一样,要求第二条线变成原版的样子。要达到上面的要求,有以下几种做法:

第一种做法:

在对第二条线进行设置的时候,清空它的状态

 1 - (void)drawRect:(CGRect)rect
 2 {
 3 //获取上下文  4 CGContextRef ctx=UIGraphicsGetCurrentContext();
 5 //绘图
 6 //第一条线  7 CGContextMoveToPoint(ctx, 20, 100);
 8 CGContextAddLineToPoint(ctx, 100, 320);
 9 10 //设置第一条线的状态
11 //设置线条的宽度 12 CGContextSetLineWidth(ctx, 12);
13 //设置线条的颜色 14 [[UIColor brownColor]set];
15 //设置线条两端的样式为圆角 16  CGContextSetLineCap(ctx,kCGLineCapRound);
17 //对线条进行渲染 18  CGContextStrokePath(ctx);
19 20 //第二条线 21 CGContextMoveToPoint(ctx, 40, 200);
22 CGContextAddLineToPoint(ctx, 80, 100);
23 24 //清空状态 25 CGContextSetLineWidth(ctx, 1);
26 [[UIColor blackColor]set];
27  CGContextSetLineCap(ctx,kCGLineCapButt);
28 29 //渲染 30  CGContextStrokePath(ctx);
31 32 }


第二种做法:

把第一条线从开始绘制到渲染的代码剪切到第二条线渲染完成之后,这样先绘制并渲染了第一条线,该线并没有对绘制信息进行过设置,显示出来的第二条线即位系统默认的效果。

 1 - (void)drawRect:(CGRect)rect
 2 {
 3 //获取上下文  4 CGContextRef ctx=UIGraphicsGetCurrentContext();
 5 //绘图
 6  7 //第二条线  8 CGContextMoveToPoint(ctx, 40, 200);
 9 CGContextAddLineToPoint(ctx, 80, 100);
10 11 //清空状态
12 // CGContextSetLineWidth(ctx, 1);
13 // [[UIColor blackColor]set];
14 15 // CGContextSetLineCap(ctx,kCGLineCapButt);
16 17 //渲染 18  CGContextStrokePath(ctx);
19 20 //第一条线 21 CGContextMoveToPoint(ctx, 20, 100);
22 CGContextAddLineToPoint(ctx, 100, 320);
23 24 //设置第一条线的状态
25 //设置线条的宽度 26 CGContextSetLineWidth(ctx, 12);
27 //设置线条的颜色 28 [[UIColor brownColor]set];
29 //设置线条两端的样式为圆角 30  CGContextSetLineCap(ctx,kCGLineCapRound);
31 //对线条进行渲染 32  CGContextStrokePath(ctx);
33 }


两种方式完成的效果相同:


但是有的情况下,必须要先画第一条线再画第二条线,要求在交叉部分,第二条线盖在第一条线的上面。如果要求是这样,那么只能使用第一种做法,但是如果现在有新的需求,要求在这个基础上再画两条线,那就需要清空ctx中的状态很多次,很麻烦。为了解决这个问题,下面给大家介绍图形上下文栈。

二、绘图的完整过程

程序启动,显示自定义的view。当程序第一次显示在我们眼前的时候,程序会调用drawRect:方法,在里面获取了图形上下文(在内存中拥有了),然后利用图形上下文保存绘图信息,可以理解为图形上下文中有一块区域用来保存绘图信息,有一块区域用来保存绘图的状态(线宽,圆角,颜色)。直线不是直接绘制到view上的,可以理解为在图形上下文中有一块单独的区域用来先绘制图形,当调用渲染方法的时候,再把绘制好的图形显示到view上去。

在绘制图形区域,会去保存绘图状态区域中查找对应的状态信息(线宽,圆角,颜色),然后在绘图区域把对第一条直线绘制完成。其实在渲染之前,就已经把直线在绘制图形区域画好了。

如图:


说明:这些示意图和本文中的程序代码块,不具备一一对应关系,只是为了说明绘图的完整过程。

调用渲染方法的时候,把绘制图形区域已经画好的图形直接显示到view上,就是我们看到的样子了。

如图:


画第二条的时候,如果没有对绘图状态进行重新设置,那么可以发现画第一天线的时候使用的绘图状态还保存在图形上下文中,在第二条线进行渲染之前,会根据第一条线(上一份绘图状态)对第二条线进行相应的设置,渲染后把第二条线显示到屏幕上。

参考代码:

 1 - (void)drawRect:(CGRect)rect
 2 {
 3 //获取上下文  4 CGContextRef ctx=UIGraphicsGetCurrentContext();
 5 //绘图
 6 //第一条线  7 CGContextMoveToPoint(ctx, 20, 100);
 8 CGContextAddLineToPoint(ctx, 100, 320);
 9 10 //设置第一条线的状态
11 //设置线条的宽度 12 CGContextSetLineWidth(ctx, 12);
13 //设置线条的颜色 14 [[UIColor brownColor]set];
15 //设置线条两端的样式为圆角 16  CGContextSetLineCap(ctx,kCGLineCapRound);
17 //对线条进行渲染 18  CGContextStrokePath(ctx);
19 20 //第二条线 21 CGContextMoveToPoint(ctx, 40, 200);
22 CGContextAddLineToPoint(ctx, 80, 100);
23 //渲染 24  CGContextStrokePath(ctx);
25 }


如果清空了状态,则在渲染之前,在绘制图形区域对第二条线进行绘制的时候,会去查找当前的绘图信息(已经更改——清空),根据绘图信息对第二条线进行绘制,调用渲染方法的时候把第二条线显示到view上。

参考代码:

 1 - (void)drawRect:(CGRect)rect
 2 {
 3 //获取上下文  4 CGContextRef ctx=UIGraphicsGetCurrentContext();
 5 //绘图
 6 //第一条线  7 CGContextMoveToPoint(ctx, 20, 100);
 8 CGContextAddLineToPoint(ctx, 100, 320);
 9 10 //设置第一条线的状态
11 //设置线条的宽度 12 CGContextSetLineWidth(ctx, 12);
13 //设置线条的颜色 14 [[UIColor brownColor]set];
15 //设置线条两端的样式为圆角 16  CGContextSetLineCap(ctx,kCGLineCapRound);
17 //对线条进行渲染 18  CGContextStrokePath(ctx);
19 20 //第二条线 21 CGContextMoveToPoint(ctx, 40, 200);
22 CGContextAddLineToPoint(ctx, 80, 100);
23 24 //清空状态 25 CGContextSetLineWidth(ctx, 1);
26 [[UIColor blackColor]set];
27  CGContextSetLineCap(ctx,kCGLineCapButt);
28 29 //渲染 30  CGContextStrokePath(ctx);
31 }


三、图形上下文栈

1.简单说明

在获取图形上下文之后,通过

CGContextSaveGState(ctx);

方法,把当前获取的上下文拷贝一份,保存一份最纯洁的图形上下文。

在画第二条线之前,使用CGContextRestoreGState(ctx);方法,还原开始的时候保存的那份最纯洁的图形上下文。

代码:

 1 - (void)drawRect:(CGRect)rect
 2 {
 3 //获取上下文  4 CGContextRef ctx=UIGraphicsGetCurrentContext();
 5 //保存一份最初的图形上下文  6  CGContextSaveGState(ctx);
 7  8 //绘图
 9 //第一条线 10 CGContextMoveToPoint(ctx, 20, 100);
11 CGContextAddLineToPoint(ctx, 100, 320);
12 13 //设置第一条线的状态
14 //设置线条的宽度 15 CGContextSetLineWidth(ctx, 12);
16 //设置线条的颜色 17 [[UIColor brownColor]set];
18 //设置线条两端的样式为圆角 19  CGContextSetLineCap(ctx,kCGLineCapRound);
20 //对线条进行渲染 21  CGContextStrokePath(ctx);
22 23 //还原开始的时候保存的那份最纯洁的图形上下文 24  CGContextRestoreGState(ctx);
25 //第二条线 26 CGContextMoveToPoint(ctx, 40, 200);
27 CGContextAddLineToPoint(ctx, 80, 100);
28 29 //清空状态
30 // CGContextSetLineWidth(ctx, 1);
31 // [[UIColor blackColor]set];
32 // CGContextSetLineCap(ctx,kCGLineCapButt);
33 34 //渲染 35  CGContextStrokePath(ctx);
36 }


2.图形上下文栈机制

画第一条线的时候,会把当前的图形上下文拷贝一份保存到图形上下文栈中。


画第二条线的时候,去图形上下文栈中取出栈顶的绘图信息,作为第二条线的状态信息,第二条线的状态信息也是据此(最初保存的那份图形上下文)进行绘制。


注意:在栈里保存了几次,那么就可以取几次(比如不能保存了1次,取两次,在取第二次的时候,栈里为空会直接挂掉)。

时间: 2024-09-03 05:55:05

iOS开发UI篇—Quartz2D使用(图形上下文栈)的相关文章

iOS开发UI篇—Quartz2D使用(绘制基本图形)

一.简单说明 图形上下文(Graphics Context):是一个CGContextRef类型的数据 图形上下文的作用:保存绘图信息.绘图状态 决定绘制的输出目标(绘制到什么地方去?)(输出目标可以是PDF文件.Bitmap或者显示器的窗口上) 相同的一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上. Quartz2D提供了以下几种类型的Graphics Context: Bitmap Graphics Context PDF Graphics Co

iOS开发UI篇—Quartz2D简单介绍

一.什么是Quartz2D Quartz 2D是⼀个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成PDF 截图\裁剪图片 自定义UI控件 二.Quartz2D在iOS开发中的价值 为了便于搭建美观的UI界面,iOS提供了UIKit框架,⾥⾯有各种各样的UI控件 UILabel:显⽰文字 UIImageView:显示图片 UIButton:同时显示图片和⽂字(能点击) 利⽤UIKi

iOS开发UI篇—Quartz2D使用(截屏)

一.简单说明 在程序开发中,有时候需要截取屏幕上的某一块内容,比如捕鱼达人游戏.如图: 完成截屏功能的核心代码:- (void)renderInContext:(CGContextRef)ctx;调用某个view的layer的renderInContext:方法即可 二.代码示例 storyboard界面搭建: 代码: 1 // 2 // YYViewController.m 3 // 01-截屏 4 // 5 // Created by apple on 14-6-12. 6 // Copyr

iOS开发UI篇—Quartz2D使用(绘图路径)

一.绘图路径 A.简单说明 在画线的时候,方法的内部默认创建一个path.它把路径都放到了path里面去. 1.创建路径 cgmutablepathref 调用该方法相当于创建了一个路径,这个路径用来保存绘图信息. 2.把绘图信息添加到路径里边. 以前的方法是点的位置添加到ctx(图形上下文信息)中,ctx 默认会在内部创建一个path用来保存绘图信息. 在图形上下文中有一块存储空间专门用来存储绘图信息,其实这块空间就是CGMutablePathRef. 3.把路径添加到上下文中. 代码示例:

iOS开发UI篇—Quartz2D使用(图片剪切)

一.使用Quartz2D完成图片剪切 1.把图片显示在自定义的view中 先把图片绘制到view上.按照原始大小,把图片绘制到一个点上. 代码: 1 - (void)drawRect:(CGRect)rect 2 { 3 UIImage *image2=[UIImage imageNamed:@"me"]; 4 [image2 drawAtPoint:CGPointMake(100, 100)]; 5 } 显示: 2.剪切图片让图片圆形展示 思路:先画一个圆,让图片显示在圆的内部,超出

iOS开发UI篇—Quartz2D使用(矩阵操作)

一.关于矩阵操作 1.画一个四边形 通过设置两个端点(长和宽)来完成一个四边形的绘制. 代码: 1 - (void)drawRect:(CGRect)rect 2 { 3 //画四边形 4 //获取图形上下文 5 CGContextRef ctx=UIGraphicsGetCurrentContext(); 6 //绘图 7 CGContextAddRect(ctx, CGRectMake(20, 50, 100, 100)); 8 //渲染 9 CGContextStrokePath(ctx)

iOS开发UI篇—Quartz2D简单使用(三)

一.通过slider控制圆的缩放 1.实现过程 新建一个项目,新建一个继承自UIview的类,并和storyboard中自定义的view进行关联. 界面搭建,如图: 代码示例: YYViewController.m文件 1 // 2 // YYViewController.m 3 // 04-对圆进行缩放 4 // 5 // Created by apple on 14-6-11. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 /

iOS开发UI篇—Quartz2D简单使用(一)

一.画直线 代码: 1 // 2 // YYlineview.m 3 // 03-画直线 4 // 5 // Created by apple on 14-6-9. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYlineview.h" 10 11 @implementation YYlineview 12 13 14 // 当自定义view第一次显示出来的时候就会调用drawRect方

iOS开发UI篇—Quartz2D(自定义UIImageView控件)

一.实现思路 Quartz2D最大的用途在于自定义View(自定义UI控件),当系统的View不能满足我们使用需求的时候,自定义View. 使用Quartz2D自定义View,可以从模仿系统的ImageView的使用开始. 需求驱动开发:模仿系统的imageview的使用过程 1.创建 2.设置图片 3.设置frame 4.把创建的自定义的view添加到界面上(在自定义的View中,需要一个image属性接收image图片参数->5). 5.添加一个image属性(接下来,拿到image之后,应