AJ分享,必须精品

首先,前面博客说过。qurza2d的上下文中有绘图信息和绘图的属性。
但是他是怎么绘制到上下午中的呢?

我们画图时候一半会用这三个步骤:
(1)获取上下文
(2)绘图
(3)渲染
这里引申出来一个问题,画两条线的时候,是怎么工作呢?

画两条相交的线

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

代码:

- (void)drawRect:(CGRect)rect
{
//获取上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//绘图
//第一条线
CGContextMoveToPoint(ctx, 30, 130);
CGContextAddLineToPoint(ctx, 250, 130); //设置第一条线的状态
//设置线条的宽度
CGContextSetLineWidth(ctx, 12);
//设置线条的颜色
[[UIColor redColor]set];
//设置线条两端的样式为圆角
CGContextSetLineCap(ctx,kCGLineCapRound);
//对线条进行渲染
CGContextStrokePath(ctx); //第二条线
CGContextMoveToPoint(ctx, 160, 30);
CGContextAddLineToPoint(ctx, 160, 200);
//渲染
CGContextStrokePath(ctx); }

这时候,我们发现,第二条我们并没有设置他的颜色和圆角等属性,但是他还是画上去了,因为他们共同用了一个上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();

画两条相交的线,并且让第二条线段变成最初的样子

这里有两种做法

第一种:清空

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

- (void)drawRect:(CGRect)rect
{
//获取上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//绘图
//第一条线
CGContextMoveToPoint(ctx, 30, 130);
CGContextAddLineToPoint(ctx, 250, 130); //设置第一条线的状态
//设置线条的宽度
CGContextSetLineWidth(ctx, 12);
//设置线条的颜色
[[UIColor redColor]set];
//设置线条两端的样式为圆角
CGContextSetLineCap(ctx,kCGLineCapRound);
//对线条进行渲染
CGContextStrokePath(ctx); //第二条线
CGContextMoveToPoint(ctx, 160, 30);
CGContextAddLineToPoint(ctx, 160, 200); //清空状态
CGContextSetLineWidth(ctx, 1);
[[UIColor blackColor]set];
CGContextSetLineCap(ctx,kCGLineCapButt); //渲染
CGContextStrokePath(ctx); }

第二种:调换顺序

先画第二条,然后画第一条。(记得画完第一个要渲染否则无效。)

- (void)drawRect:(CGRect)rect
{
//获取上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//绘图 //第二条线
CGContextMoveToPoint(ctx, 160, 30);
CGContextAddLineToPoint(ctx, 160, 200); //渲染
CGContextStrokePath(ctx); //第一条线
CGContextMoveToPoint(ctx, 30, 130);
CGContextAddLineToPoint(ctx, 250, 130); //设置第一条线的状态
//设置线条的宽度
CGContextSetLineWidth(ctx, 12);
//设置线条的颜色
[[UIColor redColor]set];
//设置线条两端的样式为圆角
CGContextSetLineCap(ctx,kCGLineCapRound);
//对线条进行渲染
CGContextStrokePath(ctx); //渲染
CGContextStrokePath(ctx); }

图形上下文栈:

上面两种方法产生的效果差不多,但是还是有略微的区别。
有的情况下,必须要先画第一条线再画第二条线,要求在交叉部分,第二条线盖在第一条线的上面。如果要求是这样,那么只能使用第一种做法,但是每次都清空,如果画的多了,非常麻烦。这里有个新的东东:图形上下文栈。

绘图的完整过程

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

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

这些示意图和本文中的程序代码块,不具备一一对应关系,只是为了说明绘图的完整过程。
调用渲染方法的时候,把绘制图形区域已经画好的图形直接显示到view上,就是我们看到的样子了。
如图:

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

简单说明图形上下文栈

在获取图形上下文之后,通过 CGContextSaveGState(ctx); 方法,把当前获取的上下文拷贝一份,保存一份最纯洁的图形上下文。
在画第二条线之前,使用CGContextRestoreGState(ctx);方法,还原开始的时候保存的那份最纯洁的图形上下文。
代码

- (void)drawRect:(CGRect)rect
{
//获取上下文
CGContextRef ctx=UIGraphicsGetCurrentContext(); //保存一份最初的图形上下文
CGContextSaveGState(ctx); //绘图
//第一条线
CGContextMoveToPoint(ctx, 30, 130);
CGContextAddLineToPoint(ctx, 250, 130); //设置第一条线的状态
//设置线条的宽度
CGContextSetLineWidth(ctx, 12);
//设置线条的颜色
[[UIColor redColor]set];
//设置线条两端的样式为圆角
CGContextSetLineCap(ctx,kCGLineCapRound);
//对线条进行渲染
CGContextStrokePath(ctx); //还原开始的时候保存的那份最纯洁的图形上下文
CGContextRestoreGState(ctx); //第二条线
CGContextMoveToPoint(ctx, 160, 30);
CGContextAddLineToPoint(ctx, 160, 200); //渲染
CGContextStrokePath(ctx); }

这样就实现了第二条在第一条上面的图片,看效果:

图解图形上下文栈

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

画第二条线的时候,去图形上下文栈中取出栈顶的绘图信息,作为第二条线的状态信息,(此时栈中一个被取还剩0个。)第二条线的状态信息也是据此进行绘制。
(栈的特点,先进后出)

注意:图形上下文栈里面保存几次就能取几次,不能存了一个你取俩,这样就崩了。

AJ学IOS(31)UI之Quartz2D图形上下文栈的更多相关文章

  1. AJ学IOS(28)UI之Quartz2D简单介绍

    AJ分享,必须精品 iOS开发UI篇—Quartz2D简单介绍 什么是Quartz2D Quartz 2D是⼀个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作: 绘制图形 : ...

  2. iOS开发UI之Quartz2D使用(绘制基本图形)

    iOS开发UI篇—Quartz2D使用(绘制基本图形) 一.简单说明 图形上下文(Graphics Context):是一个CGContextRef类型的数据 图形上下文的作用:保存绘图信息.绘图状态 ...

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

    iOS开发UI篇—Quartz2D使用(绘制基本图形) 一.简单说明 图形上下文(Graphics Context):是一个CGContextRef类型的数据 图形上下文的作用:保存绘图信息.绘图状态 ...

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

    iOS开发UI篇—Quartz2D使用(图形上下文栈) 一.qurza2d是怎么将绘图信息和绘图的属性绘制到图形上下文中去的? 说明: 新建一个项目,自定义一个view类和storyboard关联后, ...

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

    转自:http://www.cnblogs.com/wendingding/p/3782489.html 一.qurza2d是怎么将绘图信息和绘图的属性绘制到图形上下文中去的? 说明: 新建一个项目, ...

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

    iOS开发UI篇—Quartz2D简单使用(一) 一.画直线 代码: 1 // 2 // YYlineview.m 3 // 03-画直线 4 // 5 // Created by apple on ...

  7. iOS开发UI篇—Quartz2D简单介绍

    iOS开发UI篇—Quartz2D简单介绍 一.什么是Quartz2D Quartz 2D是⼀个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作: 绘制图形 : 线条\三角形\ ...

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

    iOS开发UI篇—Quartz2D简单使用(一) 一.画直线 代码: // // YYlineview.m // 03-画直线 // // Created by apple on 14-6-9. // ...

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

    iOS开发UI篇—Quartz2D使用(矩阵操作) 一.关于矩阵操作 1.画一个四边形 通过设置两个端点(长和宽)来完成一个四边形的绘制. 代码: - (void)drawRect:(CGRect)r ...

随机推荐

  1. Journal of Proteome Research | Global Proteomic Analysis of Lysine Succinylation in Zebrafish (Danio rerio) (解读人:关姣)

    文献名:Global Proteomic Analysis of Lysine Succinylation in Zebrafish (Danio rerio)(斑马鱼赖氨酸琥珀酰化的全球蛋白质组学分 ...

  2. 【攻防世界】open-source

    难度系数: 3.0 题目来源: Pediy CTF 2018 题目描述:菜鸡发现Flag似乎并不一定是明文比较的 先用:PE查壳,发现没有

  3. 采用C++实现哈夫曼树的创建并输出哈夫曼编码

    一.这篇随笔来自一道信息论的作业题,因为手动编码过于复杂,所以想到了编程解决,原题目如下图所示: 二.源代码如下: #include <iostream> #include <str ...

  4. ThreadPoolTaskExecutor 中 corePoolSize vs. maxPoolSize

    1. 概览 Spring中的 ThreadPoolTaskExecutor 是一个 JavaBean ,提供围绕java.util.concurrent.ThreadPoolExecutor 的抽象实 ...

  5. dirname,basename的用法与用途

    #dirname介绍 当对文件使用dirname时,返回文件的上级目录,输出是否是绝对路径取决于输入的文件名是绝对路径 如果对目录使用,则返回上级目录 basename命令与dirname相反,读取文 ...

  6. 听说用 Lombok 可以早点下班?

    听说隔壁用 Lombok 的六点就下班了,我也想六点下班! 好的,那么这篇文章就介绍下什么是 Lombok,Lombok 做了什么以及 Lombok 是怎么做的? 在介绍之前,先通过是否使用 Lomb ...

  7. 强化学习之一:从TensorFlow开始(Start from TensorFlow)

    本文是对Tensorflow官方教程的个人(tomqianmaple@outlook.com)中文翻译,供大家学习参考. 官方教程链接 tf的扬帆起航Getting Started With Tens ...

  8. socket,实现服务器和客户端对话

    服务器: #define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string>#include<WinSock ...

  9. IOS 手动添加第三方库报错问题

    当不想使用CocoaPods来管理和使用第三方库的时候,就需要手动添加和配置这些第三方库,难免会出现一些问题,主要问题汇总如下: 1.AFNetworking.NKNetWork.ZxingObjC等 ...

  10. iOS 继承

    是否使用继承需要考虑三个点: 父类只是给子类提供服务,并不涉及子类的业务逻辑 层级关系明显,功能划分清晰,父类和子类各做各的. 父类的所有变化,都需要在子类中体现,也就是说此时耦合已经成为需求 万不得 ...