美文网首页
iOS-图形上下文栈、矩阵操作

iOS-图形上下文栈、矩阵操作

作者: Imkata | 来源:发表于2019-11-11 14:45 被阅读0次

一. 为什么使用图形上下文栈

1. 绘图的完整过程

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

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

如图: 1.png 2.png 3.png

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

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

2. 代码示例

- (void)drawRect:(CGRect)rect
{
    //获取上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //绘图
    //第一条线
    CGContextMoveToPoint(ctx, 20, 100);
    CGContextAddLineToPoint(ctx, 100, 320);

    //设置第一条线的状态
    //设置线条的宽度
    CGContextSetLineWidth(ctx, 12);
    //设置线条的颜色
    [[UIColor brownColor]set];
    //设置线条两端的样式为圆角
    CGContextSetLineCap(ctx,kCGLineCapRound);
    //对线条进行渲染
    CGContextStrokePath(ctx);

    //第二条线
    CGContextMoveToPoint(ctx, 40, 200);
    CGContextAddLineToPoint(ctx, 80, 100);
    //渲染
    CGContextStrokePath(ctx);
}

效果图:

效果图.png

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

代码示例:

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

效果图:

效果图.png

如果现在有新的需求,要求在这个基础上再画两条线,那就需要清空ctx中的状态很多次,很麻烦,为了解决这个问题,下面给大家介绍图形上下文栈。

二. 图形上下文栈

将当前的图形上下文状态copy一份到栈,这个栈就是图形上下文栈,利用图形上下文栈我们可以恢复绘图状态。

相关API:

CGContextSaveGState() //保存图形上下文状态使用
CGContextRestoreGState() //恢复图形上下文状态使用

CGContextRestoreGState不能一直调用,这要看图形上下文栈有多少图形上下文状态可恢复。

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

代码:

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

效果图和上面一样,这样就不用一直清空状态了。

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

三. 矩阵操作

利用矩阵操作,我们可以把画出的图形进行旋转、缩放、平移操作。

旋转: CGContextRotateCTM()
缩放: CGContextScaleCTM()
平移: CGContextTranslateCTM()

示例:先画个正方形和圆形

- (void)drawRect:(CGRect)rect
{
    //画四边形
    //获取图形上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();

    //绘图
    //画正方形
    CGContextAddRect(ctx, CGRectMake(20, 50, 100, 100));
    //画一个圆
    CGContextAddEllipseInRect(ctx, CGRectMake(200, 200, 50, 50));

    //渲染
    CGContextStrokePath(ctx);
}
未旋转.png

1. 旋转

方法:

CGContextRotateCTM(<#CGContextRef c#>, <#CGFloat angle#>)
//接收两个参数(图形上下文,弧度)

注意:设置矩阵操作必须要在添加绘图信息之前,如果设置在添加绘图信息之后的话,此时它已经画完了,就无效了。

示例:

- (void)drawRect:(CGRect)rect
{
    //画四边形
    //获取图形上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();

    //矩阵操作, 旋转45度
    //注意点:设置矩阵操作必须要在添加绘图信息之前
    CGContextRotateCTM(ctx, M_PI_4);
     
    //绘图
    //画正方形
    CGContextAddRect(ctx, CGRectMake(20, 50, 100, 100));
    //画一个圆
    CGContextAddEllipseInRect(ctx, CGRectMake(200, 200, 50, 50));
    //渲染
    CGContextStrokePath(ctx);
}
旋转后.png

提示:旋转的时候,是整个layer都旋转了。

2. 缩放

方法:

CGContextScaleCTM(<#CGContextRef c#>, <#CGFloat sx#>, <#CGFloat sy#>)
//接收三个参数(图形上下文,x方向的缩放比例,y方向上的缩放比例

示例:

- (void)drawRect:(CGRect)rect
{
    //画四边形
    //获取图形上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();

    //缩放,x方向缩放0.5倍,y方向缩放1.5倍
    //注意点:设置矩阵操作必须要在添加绘图信息之前
    CGContextScaleCTM(ctx, 0.5, 1.5);
      
    //绘图
    //画正方形
    CGContextAddRect(ctx, CGRectMake(20, 50, 100, 100));
    //画一个圆
    CGContextAddEllipseInRect(ctx, CGRectMake(200, 200, 50, 50));
    //渲染
    CGContextStrokePath(ctx);
}
缩放.png

3. 平移

方法:

CGContextTranslateCTM(<#CGContextRef c#>, <#CGFloat tx#>, <#CGFloat ty#>)
//接收三个参数(图形上下文,x方向的偏移量,y方向上的偏移量)

示例:

- (void)drawRect:(CGRect)rect
{
    //画四边形
    //获取图形上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();

    //平移,x方向移动50,y方向移动100
    //注意点:设置矩阵操作必须要在添加绘图信息之前
    CGContextTranslateCTM(ctx, 50, 100);
      
    //绘图
    //画正方形
    CGContextAddRect(ctx, CGRectMake(20, 50, 100, 100));
    //画一个圆
    CGContextAddEllipseInRect(ctx, CGRectMake(200, 200, 50, 50));
    //渲染
    CGContextStrokePath(ctx);
}
平移.png

相关文章

  • 图形上下文状态栈与矩阵操作

    图形上下文状态栈与矩阵操作 矩阵操作(关注核心代码即可) 图形上下文状态栈(关注核心代码即可)

  • iOS-图形上下文栈、矩阵操作

    一. 为什么使用图形上下文栈 1. 绘图的完整过程 程序启动,显示自定义的view,当程序第一次显示在我们眼前的时...

  • 图形上下文状态栈、矩阵操作

    图形上下文状态栈:用来保存绘图的状态(颜色,线宽等等)。1、首先开启一个图形上下文2、开启一个路径设置起始点3、设...

  • Quartz2D-2

    1.矩阵操作 1.1.平移 1.2.旋转 1.3.缩放 1.4.注意 2.图形上下文栈 2.1.通过绘图原理来理解...

  • CG系统方法

    方法解析 图形上下文栈 矩阵操作 功能:缩放sx:水平方向上的缩放。所有点的 X 坐标都相当于乘以 sx 因子。s...

  • Quartz2D之矩阵操作

    上下文的矩阵操作 平移 旋转 缩放

  • OpenGL_矩阵压栈和出栈

    1. 压栈和出栈的理解 压栈出栈操作的是矩阵 用来记录矩阵的状态 压栈PushMatrix和出栈PopMatrix...

  • OpenGL 出栈压栈理解分析

    1.OpenGL压栈出栈作用概念 1.压栈出栈操作的是矩阵,一般分为模型视图矩阵和投影矩阵 2.出栈压栈是针对顶点...

  • 图形上下文栈

    绘图的完整过程 程序启动,显示自定义的view。当程序第一次显示在我们眼前的时候,程序会调用drawRect:方法...

  • 图形上下文栈

    看了几篇网上图形上下文栈的讲解,不知道是我理解有问题,还是没找到好文章,还是压根作者也不是特别明白,欺骗我。最后决...

网友评论

      本文标题:iOS-图形上下文栈、矩阵操作

      本文链接:https://www.haomeiwen.com/subject/gbdtictx.html