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个。)第二条线的状态信息也是据此进行绘制。
(栈的特点,先进后出)

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

最新文章

  1. JS中如何输出空格
  2. CF444C. DZY Loves Colors[线段树 区间]
  3. 2016HUAS_ACM暑假集训4D - 计数,排列
  4. findViewById返回null
  5. C2解题报告合集~
  6. Android Studio2.x版本无法自动关联源码的解决方法
  7. Cool!15个创意的 CSS3 文本效果【下篇】
  8. mysql workbench建表时PK,NN,UQ,BIN,UN,ZF,AI
  9. 吐个槽,对VB6.0 还有VBS 说ByeBye
  10. 关于Oracle过程,函数的经典例子及解析
  11. 面向对象的JavaScript系列二,继承
  12. Java中到底有没有指针;同时注意引用和指针的区别
  13. SHDP--Working With HBase(一)之基本介绍
  14. B - Moving Tables
  15. PAT1029.Median (25)
  16. UDP和TCP的差异
  17. leetcode-956. 最高的广告牌
  18. semantic segmentation with deeplearning
  19. vue 去掉路由中的#
  20. Codeforces 868D Huge Strings - 位运算 - 暴力

热门文章

  1. ERP系统功能及部署方式
  2. SpringBoot 拦截器 && 拦截之后返回前台自定义格式
  3. 文本编辑器之kindeditor
  4. python环境变量忘记配置
  5. 【转载】因为我们是OIer
  6. 【笔记3-27】Python语言基础
  7. 走近源码:Redis如何清除过期key
  8. nim博弈 LightOJ - 1253
  9. 移植OPENNI到DM6446上面
  10. ConcurrentHashMap红黑树的实现