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, , );
  8. CGContextAddLineToPoint(ctx, , );
  9.  
  10. //第二条线
  11. CGContextMoveToPoint(ctx, , );
  12. CGContextAddLineToPoint(ctx, , );
  13. //渲染
  14. CGContextStrokePath(ctx);
  15.  
  16. }
效果图:
设置线段的宽度:两头为圆形,颜色等。
代码和效果图(发现第二条线也被渲染成第一条线的样式和状态)
  1. - (void)drawRect:(CGRect)rect
  2. {
  3. //获取上下文
  4. CGContextRef ctx=UIGraphicsGetCurrentContext();
  5. //绘图
  6. //第一条线
  7. CGContextMoveToPoint(ctx, , );
  8. CGContextAddLineToPoint(ctx, , );
  9.  
  10. //设置第一条线的状态
  11. //设置线条的宽度
  12. CGContextSetLineWidth(ctx, );
  13. //设置线条的颜色
  14. [[UIColor brownColor]set];
  15. //设置线条两端的样式为圆角
  16. CGContextSetLineCap(ctx,kCGLineCapRound);
  17. //对线条进行渲染
  18. CGContextStrokePath(ctx);
  19.  
  20. //第二条线
  21. CGContextMoveToPoint(ctx, , );
  22. CGContextAddLineToPoint(ctx, , );
  23. //渲染
  24. CGContextStrokePath(ctx);
  25.  
  26. }

效果图:

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

第一种做法:
在对第二条线进行设置的时候,清空它的状态
  1. - (void)drawRect:(CGRect)rect
  2. {
  3. //获取上下文
  4. CGContextRef ctx=UIGraphicsGetCurrentContext();
  5. //绘图
  6. //第一条线
  7. CGContextMoveToPoint(ctx, , );
  8. CGContextAddLineToPoint(ctx, , );
  9.  
  10. //设置第一条线的状态
  11. //设置线条的宽度
  12. CGContextSetLineWidth(ctx, );
  13. //设置线条的颜色
  14. [[UIColor brownColor]set];
  15. //设置线条两端的样式为圆角
  16. CGContextSetLineCap(ctx,kCGLineCapRound);
  17. //对线条进行渲染
  18. CGContextStrokePath(ctx);
  19.  
  20. //第二条线
  21. CGContextMoveToPoint(ctx, , );
  22. CGContextAddLineToPoint(ctx, , );
  23.  
  24. //清空状态
  25. CGContextSetLineWidth(ctx, );
  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, , );
  9. CGContextAddLineToPoint(ctx, , );
  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, , );
  22. CGContextAddLineToPoint(ctx, , );
  23.  
  24. //设置第一条线的状态
  25. //设置线条的宽度
  26. CGContextSetLineWidth(ctx, );
  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, , );
  8. CGContextAddLineToPoint(ctx, , );
  9.  
  10. //设置第一条线的状态
  11. //设置线条的宽度
  12. CGContextSetLineWidth(ctx, );
  13. //设置线条的颜色
  14. [[UIColor brownColor]set];
  15. //设置线条两端的样式为圆角
  16. CGContextSetLineCap(ctx,kCGLineCapRound);
  17. //对线条进行渲染
  18. CGContextStrokePath(ctx);
  19.  
  20. //第二条线
  21. CGContextMoveToPoint(ctx, , );
  22. CGContextAddLineToPoint(ctx, , );
  23. //渲染
  24. CGContextStrokePath(ctx);
  25. }
如果清空了状态,则在渲染之前,在绘制图形区域对第二条线进行绘制的时候,会去查找当前的绘图信息(已经更改——清空),根据绘图信息对第二条线进行绘制,调用渲染方法的时候把第二条线显示到view上。
参考代码:
  1. - (void)drawRect:(CGRect)rect
  2. {
  3. //获取上下文
  4. CGContextRef ctx=UIGraphicsGetCurrentContext();
  5. //绘图
  6. //第一条线
  7. CGContextMoveToPoint(ctx, , );
  8. CGContextAddLineToPoint(ctx, , );
  9.  
  10. //设置第一条线的状态
  11. //设置线条的宽度
  12. CGContextSetLineWidth(ctx, );
  13. //设置线条的颜色
  14. [[UIColor brownColor]set];
  15. //设置线条两端的样式为圆角
  16. CGContextSetLineCap(ctx,kCGLineCapRound);
  17. //对线条进行渲染
  18. CGContextStrokePath(ctx);
  19.  
  20. //第二条线
  21. CGContextMoveToPoint(ctx, , );
  22. CGContextAddLineToPoint(ctx, , );
  23.  
  24. //清空状态
  25. CGContextSetLineWidth(ctx, );
  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, , );
  11. CGContextAddLineToPoint(ctx, , );
  12.  
  13. //设置第一条线的状态
  14. //设置线条的宽度
  15. CGContextSetLineWidth(ctx, );
  16. //设置线条的颜色
  17. [[UIColor brownColor]set];
  18. //设置线条两端的样式为圆角
  19. CGContextSetLineCap(ctx,kCGLineCapRound);
  20. //对线条进行渲染
  21. CGContextStrokePath(ctx);
  22.  
  23. //还原开始的时候保存的那份最纯洁的图形上下文
  24. CGContextRestoreGState(ctx);
  25. //第二条线
  26. CGContextMoveToPoint(ctx, , );
  27. CGContextAddLineToPoint(ctx, , );
  28.  
  29. //清空状态
  30. // CGContextSetLineWidth(ctx, 1);
  31. // [[UIColor blackColor]set];
  32. // CGContextSetLineCap(ctx,kCGLineCapButt);
  33.  
  34. //渲染
  35. CGContextStrokePath(ctx);
  36. }
 
2.图形上下文栈机制
画第一条线的时候,会把当前的图形上下文拷贝一份保存到图形上下文栈中。
画第二条线的时候,去图形上下文栈中取出栈顶的绘图信息,作为第二条线的状态信息,第二条线的状态信息也是据此(最初保存的那份图形上下文)进行绘制。
           
注意:在栈里保存了几次,那么就可以取几次(比如不能保存了1次,取两次,在取第二次的时候,栈里为空会直接挂掉)。

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

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

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

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

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

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

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

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

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

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

    iOS开发UI篇—Quartz2D使用(图片剪切) 一.使用Quartz2D完成图片剪切 1.把图片显示在自定义的view中 先把图片绘制到view上.按照原始大小,把图片绘制到一个点上. 代码: - ...

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

    iOS开发UI篇—Quartz2D简单使用(三) 一.通过slider控制圆的缩放 1.实现过程 新建一个项目,新建一个继承自UIview的类,并和storyboard中自定义的view进行关联. 界 ...

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

    iOS开发UI篇—Quartz2D使用(绘图路径) 一.绘图路径 A.简单说明 在画线的时候,方法的内部默认创建一个path.它把路径都放到了path里面去. 1.创建路径  cgmutablepat ...

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

    iOS开发UI篇—Quartz2D使用(截屏) 一.简单说明 在程序开发中,有时候需要截取屏幕上的某一块内容,比如捕鱼达人游戏.如图: 完成截屏功能的核心代码:- (void)renderInCont ...

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

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

随机推荐

  1. Handle源码分析,深入群内了解风骚的Handle机制

    Hanlder的使用方式一: private static Handler mHandler = new Handler(){ public void handleMessage(android.os ...

  2. phpcms无法读取index.html的解决步骤

    代码如下: phpcms\modules\content\classes\html.class.php 查找 复制代码 代码如下: /** * 更新首页 */ public function inde ...

  3. shiro 从入门到放弃

    Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Security做的功能强大 ...

  4. python 的 from import 机制

    [A.py] from B import D class C:pass [B.py] from A import C class D:pass 为什么执行A的时候不能加载D呢? 如果将A.py改为:i ...

  5. Python3基础 print 查看一个列表中存储的所有内容

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  6. [转](五)unity4.6Ugui中文教程文档-------概要-UGUI Interaction Components

    大家好,我是孙广东.   转载请注明出处:http://write.blog.csdn.net/postedit/38922399 更全的内容请看我的游戏蛮牛地址:http://www.unityma ...

  7. Django ModelForm and Form

    django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm 关于django的表单系统,主要分两种 基于django.forms.Form 基于dj ...

  8. 常用webservice接口

    商业和贸易: 1.股票行情数据 WEB 服务(支持香港.深圳.上海基金.债券和股票:支持多股票同时查询) Endpoint: http://webservice.webxml.com.cn/WebSe ...

  9. hdu4057Rescue the Rabbit(ac自动机+dp)

    链接 当时是因为没有做出来这道题才开了自动机的专题,现在看看还是比较简单的. 因为每个病毒串只算一次,只有10个病毒串,可以状压一下哪些状态是可以达到的,最后取一个最大值. #include < ...

  10. UiAutomator环境搭建及详细操作

    一.环境搭建 1.1 必备条件 JDK SDK(API高于15) Eclipse(安装ADT插件) ANT(用于编译生成的jar) 安装JDK并添加环境变量 1.2 详细步骤 1.安装JDK并添加环境 ...