美文网首页绘制QuartZ 2DiOS动画
Core Graphics框架 : 一个让程序猿成为视觉设计师的

Core Graphics框架 : 一个让程序猿成为视觉设计师的

作者: 神经骚栋 | 来源:发表于2016-09-08 13:54 被阅读1988次

    Core Graphics简介


    说Core Graphics框架之前,我们首先要先说一下,在iOS中绘制图形的方式,其形式主要有三种.

    • 1.创建一个UI视图,并且使用"drawRect:"方法添加到Quartz 2D绘制代码中,也就是今天所要说的Core Graphics框架.
    • 2.使用Core Animation层,并且通过委托方法想Core Animation层提供图形内容.
    • 3.通过 OpenGL ES 渲染图形

    其结构图如下所示.从图中我们看到的是是不管使用者还是开发者最容易接触到的先是UIKit框架,然后再就是Core Graphics,Core Animation和OpenGL ES,Core Graphics,Core Animation这两个框架虽然我们没有用过,但是我们最少听过,但是OpenGL ES是什么鬼?OpenGL ES这个有点日后再议,今天主题不是它,而是我们的Core Graphics框架.
    </b>
    Core Graphics其实是一套基于C语言的API框架,使用了Quartz作为绘图引擎。这也就意味着Core Graphics不是面向对象的。但是这句话对我们并无伤大雅.也就是然并卵~,我们只需要知道如何使用Core Graphics框架就好.下面我就对Core Graphics框架相关知识一一道来.

    CGContextRef (图形上下文)


    图形上下文,不要被它的名字吓到,其实你就可以理解为是一个画布,我们要绘制任何东西总要有个东西接受我们绘制的东西吧?所以CGContextRef就出现了,对于CGContextRef有几个注意点,iOS是允许新建CGContextRef的,但是我们通常不这么干,因为创建一个新的CGContextRef,但是性能和内存的使用上,效率是非常低的。所以我们会在"drawRect:"方法中直接获取当前View的CGContextRef.代码如下.

        //获取当前View的图形上下文
        CGContextRef contextRef = UIGraphicsGetCurrentContext();
    
    

    CGPath(路径)


    那么画板有了,我们是不是应该可以作图了?是的,但是如何才能确定出一个图形呢?不管是什么图形,首先我们要先确定它的边框,一旦确定了一个边框,我们就可以设置边框的各种绘图属性、边框内部区域的绘图属性、绘制边框还是内部区域等。这时候,CGPath就闪亮登场了.CGPath也就是路径信息,一开始如果没有接触过PS过的童鞋可能不知道路径到底是一个什么,通俗一点讲,不管你画什么图形,直线也好,多边形也罢,你的画笔都要从一个开始位置开始,然后 "持续"移动画笔,画出一个图形来.终止于一个结束点,如果画笔为无色,画笔划过的线可以理解为路径.当然了,现实中哪有无色的画笔?哈哈.好了言归正传.Core Graphics框架其实已给我们分装好了很多的调用函数,方便我们调用,我们就看几个常用调用函数.

    新建路径(常用于创建直线,也可以用直接拼接成多边形)

    CGMutablePathRef path = CGPathCreateMutable();
    

    新建矩形,rect是矩形的位置和大小信息,transform是仿射变换参数.

    CGPathCreateWithRect(CGRect rect,const CGAffineTransform * __nullable transform)
    

    新建圆,rect是圆的位置和大小信息,cornerWidth和cornerHeight是圆的半径,通过设置这两个参数,我们可以生成椭圆,transform是仿射变换参数.

    CGPathCreateWithRoundedRect(CGRect rect,CGFloat cornerWidth, CGFloat cornerHeight,const CGAffineTransform * __nullable transform)
    

    把路径添加到图形上下文中,c是图形上下文参数,path是路径参数.这里有一点要注意,如果你创建好路径,并且调用下面添加方法,我们在View页面上是看不到的路径,这是为什么呢?还记得我们前面说用"无色"的画笔做出的图形,可以理解为路径.就是因为没有涂色,所以看不见.

    CGContextAddPath(CGContextRef __nullable c,CGPathRef __nullable path)
    

    绘制路径函数,我们把路径的属性设置完成之后,就需要绘制函数,记住添加和绘制是两回事~~~.c代表着图形上下文.mode代表着填充类型.

    CGContextDrawPath(CGContextRef __nullable c,  CGPathDrawingMode mode)
    

    释放删除路径函数,有人就会问,我们在ARC开发环境下,会自动释放呀,NONONO~~,因为CGPathCreateMutable方法返回的路径是一个Core Fundation Object.而这并不在ARC的管理范围之内.所以需要使用下面函数手动释放对象. path代表着要删除的路径.

    CGPathRelease(CGPathRef __nullable path)
    

    CGAffineTransform(仿射变换)


    那么,就算我们已经已经做好了图形了,可能我们需要对图形做平移,缩放,旋转的时候,我们该如何实现?CGAffineTransform是一个仿射变换的结构体,专门用于进行二维平面的几何变换(平移,旋转,缩放).而且比较贴心的是系统(到底是系统还是程序猿?😂)已经帮我们分装了一些函数,我们不需要直接设置CGAffineTransform,直接调用函数即可,下面我们就看一下CGAffineTransform的结构体形式以及一些常用的仿射变换函数.常用函数有一个地方要注意,就是不管是哪一种仿射变换,都有两个函数,一个是在初始的状态上进行变换,一个是在前一个状态上进行变换.

    CGAffineTransform的结构体如下所示,如果想要了解CGAffineTransform就要引入齐次函数的概念,这个以后再说.

    struct CGAffineTransform {
      CGFloat a, b, c, d;
      CGFloat tx, ty;
    };
    
    

    平移函数,tx和ty代表着偏移量.

     CGAffineTransformMakeTranslation(CGFloat tx,CGFloat ty)
    

    缩放函数,sx和sy代表着x轴和y轴的缩放比例.

    CGAffineTransform CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)
    

    旋转函数,angle代表着旋转的角度.逆时针为正,顺时针为负。

    CGAffineTransformMakeRotation(CGFloat angle)
    

    文字的绘制


    上面我们看了一下如何创建多边形,那么显示当中不但有图形还会出现文字,文字我们又该如何处理呢?文字的绘制比较简单,我们只要直接使用需要绘制的字符串直接调用drawInRect:drawAtPoint:这两个方法即可.具体内容以后再说,这篇我们只做简单的了解.下面我们就对这两个绘制方法进行简单的介绍.

    rect代表着绘制的文字的大小和位置信息.attrs代表着文本属性.

    - (void)drawInRect:(CGRect)rect withAttributes:(nullable NSDictionary<NSString *, id> *)attrs 
    

    point代表着绘制的文字的大小信息.attrs代表着文本属性.

    - (void)drawAtPoint:(CGPoint)point withAttributes:(nullable NSDictionary<NSString *, id> *)attrs 
    

    重新绘制.


    我们知道绘制整体过程是在View的- (void)drawRect:(CGRect)rect;方法中进行.如果我们想要重新绘制图形该如何办呢?我们并不会直接调用drawRect:这个绘制方法,而是调用如下方法.

    //重新绘制.
    - (void)setNeedsDisplay;
    

    从Core Graphics框架到Hello World


    上面喋喋不休的讲了一大堆,可能童鞋早已擦拳磨掌准备大干一场了.接下来我们就开始Hello World吧.

    首先,我们在工程中新建一个UIView对象.这里我创建的是SDView,大家可自行设定.

    创建好了UIView对象之后,我们就在SDView.h的- (void)drawRect:(CGRect)rect;方法中进行绘制工作,首先我们要先获取View的图形上下文.毕竟自己创建的效率低嘛~

        //获取上下文
        CGContextRef contextRef = UIGraphicsGetCurrentContext();
    
    

    获取完成之后,Hello World之路就从一条直线开始吧,首先我们先设置创建一个路径.

        //创建路径
        CGMutablePathRef path = CGPathCreateMutable();
    

    创建完路径,我们就设置路径的起始位置和终点位置,并且把它添加上图形上下文上.

        CGPathMoveToPoint(path, nil, 100, 100);
        
        CGPathAddLineToPoint(path, nil, 200, 200);
        
        CGContextAddPath(contextRef, path);
    

    如果现在路径已经做好了,是一条从(100,100)到(200,200)的直线.并且已经添加到图形上下文中了.这时候如果我们直接绘制并不能看到我们的路径这是为什么呢?还是因为"无色"呀,没有设置颜色,我们怎么会看到.所以下面我们就对路径的属性进行相关的设置.

    上图中,笔触颜色为红色,其实也就是边框的颜色,因为直线只是一条直线,所以我们设置它的笔触颜色即可.设置代码如下,我们需要输入的是RGB值.

        CGContextSetRGBStrokeColor(contextRef, 1.0, 0, 0, 1);//设置笔触颜色
    

    下面这行代码是设置填充色,意思是填充路径圈起来的内部颜色.直线设置也无伤大雅,因为没有圈起来任何区域,像多边形,就能看出效果来了.

        CGContextSetRGBFillColor(contextRef, 0, 1.0, 0, 1);//设置填充色
    

    设置线条的宽度,如果不进行设置,默认好像设置为1.0

        CGContextSetLineWidth(contextRef, 5.0);//设置线条宽度
    
    

    对于设置顶点样式和连接点样式,我们需要注意的是它的概念,顶点就是两头的点,即开始节点和终止节点.连接点呢,即为中间转折点,比如创建矩形,就会产生两个连接点.

        CGContextSetLineCap(contextRef, kCGLineCapButt);//设置顶点样式
        CGContextSetLineJoin(contextRef, kCGLineJoinRound);//设置连接点样式
    

    上面呢,我们已经把属性设置完成了,接下来就是绘制了.

    绘制路径,因为我们只需要绘制路径部分,所以我们的填充类型选择是kCGPathFillStroke;

        CGContextDrawPath(contextRef, kCGPathFillStroke);//最后一个参数是填充类型
        
    

    最后,我们需要手动释放我们的路径.原因看路径相关部分.

        CGPathRelease(path);
    

    这样整体的Hello world绘制部分就完成了,现在我们需要在ViewController中调用一下,看看我们的绘制成果.代码如下.

    #import "ViewController.h"
    #import "SDView.h"
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        SDView *view = [[SDView alloc]initWithFrame:self.view.frame];
        view.backgroundColor = [UIColor whiteColor];
        [self.view addSubview:view];
    
    }
    
    @end
    
    

    最后command +R运行一下,看一下效果图,我们成功的绘制出了我们第一条直线.

    Core Graphics优势


    说了这么多,现在我们只是知道Core Graphics框架是iOS实现图像的一种方式,但是什么要深入的研究Core Graphics呢?或者说Core Graphics直接绘图有着这样的优势呢?

    因为Core Graphics更接近底层,越接近底层就越快速越高效.这自是不用多说,同时呢,使用Core Graphics可以大大减少应用程序的大小,这又是从何说起呢?举个例子来说,如下图所示.我们现在要在屏幕上显示一个文字,通常我们会怎么干呢?我们会先创建一个UILabel对象,然后把文字添加上,我们需要绘制的部分是UILable对象和文字两部分,现在,我们使用Core Graphics可以只绘制文字这一部分,对系统内存的损耗大大减少.再就是仿射变换结构体的存在,我们可以对绘制的部分进行一些平移,缩放,旋转等操作.


    </br>


    恩恩,Core Graphics框架 ,一个让程序猿成为视觉设计师的框架,hello world之路就到这了.最后附上本文的Demo.后期,我会对Core Graphics框架中所遇到的相关知识进行详细的分析解说,希望大家继续关注骚栋.

    --->传送门💾

    相关文章

      网友评论

      • saman0:已经关注了
      • Feringlan:嗨呀,很骚
      • 阿随向前冲:不明觉厉
        神经骚栋:@阿随向前冲 必须的嘛~PS方面要跟随阿随大神的脚步~~~ :smile:
        阿随向前冲:@神经骚栋 :relaxed: 看到了熟悉的头图字体,哈哈哈
        神经骚栋: @阿随向前冲 阿随大神的文采和内容才是不明觉厉呢!😬😬😬
      • YungFan:不错 上首页了
        神经骚栋: @YungFan 哈哈,还有一篇 仿射变换与齐次坐标的好像也干到首页上了
        YungFan:@神经骚栋 一不小心刷到了
        神经骚栋: @YungFan 哈哈,谢谢哥还这么关注我……

      本文标题:Core Graphics框架 : 一个让程序猿成为视觉设计师的

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