美文网首页绘图相关
iOS 绘图API之Core Graphics系统学习(一)

iOS 绘图API之Core Graphics系统学习(一)

作者: 雪中夜归人 | 来源:发表于2018-01-24 11:24 被阅读216次

    前言

      iOS支持两套图形API族:Core Graphics和OpenGL ES。OpenGL ES是跨平台的图形API,属于OpenGL的一个简化版本。而QuartZ 2D是苹果公司开发的一套API,它是Core Graphics Framewore的一部分。
      本文中主要是对Core Graphics框架的学习总结。

      对于一个初学者来说,UIKit和Core Graphics两个支持绘图的框架常常令我们感到迷惑。

    UIKit

      UIKit是一组Objective-C API,为线条图形、Quartz图像和颜色操作提供Objective-C封装,并提供2D绘制、图像处理及用户接口级别的动画。
      UIKit包含UIBezierPath(绘制线、角度、椭圆及其它图形)、UIImage(显示图像)、UIColor(颜色操作)、UIFont和UIScreen(提供字体和屏幕信息)等类,它在位图图形环境、PDF图形环境上进行绘制和操作功能,也提供对标准视图的支持,也提供对打印功能的支持。
      使用UIKit,你只能在当前上下文中绘图。

    Core Graphics

      这是一个绘图专用的API族,它经常被称为QuartZ或者QuartZ 2D。Core Graphics 是iOS上所有绘图功能的基石,包括UIKit(UIKit是对Core Graphics的进一步封装)。
      使用Core Graphics之前需要指定一个用于绘图的图形上下文(CGContextRef),这个图形上下文会在每个绘图函数中都会用到。

      至此,我们了解了这两个框架的基本关系,而这两个框架中都提到了图形上下文(图形场景)。获得一个图形上下文是我们完成绘图任务的第一步,可以将图形上下文理解为一块画布。那么下边介绍三种获得图形上下文的方法:

    - (void)drawRect:(CGRect)rect方法

      在此方法中,UIKit框架可以直接绘图,而Core Graphics可以通过UIGraphicsGetCurrentContext函数获取当前的图形上下文。

    - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

      在此方法中,直接传入了图形上下文,但是该上下文不一定是当前的图形上下文,所以在UIKit框架下绘图时,需要调用UIGraphicsPushContext()函数将该上下文变为当前上下文,结束时调用UIGraphicsPopContext()函数还原上下文。而Core Graphics框架下可以直接使用该上下文。

    UIGraphicsBeginImageContextWithOptions函数

      此函数获取图形上下文的规则跟drawRect:方法是一样的。利用该上下文,你就可以在其上进行绘图,并生成图片。调用UIGraphicsGetImageFromCurrentImageContext函数可从当前上下文中获取一个UIImage对象。记住在你所有的绘图操作后别忘了调用UIGraphicsEndImageContext函数关闭图形上下文。
      这里主要解释一下三个参数的含义。第一个参数表示所要创建的图片尺寸;第二个参数用来指定生成图片的背景是否为不透明,YES表示不透明,则得到的是黑色的背景;第三个参数制定生成图片的缩放因子,这个缩放因子与UIImage的scale属性所指的含义是一致的。0则表示让图片的缩放因子根据屏幕的分辨率而变化。

    基于两大绘图框架和三种获取图形上下文的方法的六种绘图形式

    举例说明:绘制一个蓝色的圆
    第一种绘图形式:基于UIKit框架(即使用UIBezierPath)在UIView的子类方法drawRect:中实现。

    - (void) drawRect: (CGRect) rect {
       UIBezierPath* p = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0,100,100)];
       [[UIColor blueColor] setFill];
       [p fill];
    }
    

    第二种绘图形式:基于Core Graphics框架在UIView的子类方法drawRect:中实现。

    - (void) drawRect: (CGRect) rect {
        CGContextRef con = UIGraphicsGetCurrentContext();
        CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));
        CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
        CGContextFillPath(con);
    }
    

    第三种绘图形式:基于UIKit框架(即使用UIBezierPath) 在UIView的子类方法drawLayer:inContext:中实现。

    - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
        [super drawLayer:layer inContext:ctx];
        UIGraphicsPushContext(ctx);
        UIBezierPath* p = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0,100,100)];
        [[UIColor blueColor] setFill];
        [p fill];
        UIGraphicsPopContext();
    }
    

    PS:同时此方法必须重写drawRect:方法,否则上边的方法不会被调用。
    详细了解这块的调用逻辑可以看这篇文章
    iOS的绘图之drawRect和drawLayer:inContext
    第四种绘图形式: 使用Core Graphics在drawLayer:inContext:方法中实现同样操作,代码如下:

    - (void)drawLayer:(CALayer*)lay inContext:(CGContextRef)con {
        CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));
        CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
        CGContextFillPath(con);
    }
    

      最后,演示UIGraphicsBeginImageContextWithOptions的用法,并从上下文中生成一个UIImage对象。生成UIImage对象的代码可以在任何地方被使用,它没有上述绘图方法那样的限制。

    第五种绘图形式: 使用UIKit实现:

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0);
    UIBezierPath* p = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,100,100)];
    [[UIColor blueColor] setFill];
    [p fill];
    UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    

    第六种绘图形式: 使用Core Graphics实现:

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0);
    CGContextRef con = UIGraphicsGetCurrentContext();
    CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));
    CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
    CGContextFillPath(con);
    UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    

    UIKit和Core Graphics可以在相同的图形上下文中混合使用。在iOS 4.0之前,使用UIKit和UIGraphicsGetCurrentContext被认为是线程不安全的。而在iOS4.0以后苹果让绘图操作在第二个线程中执行解决了此问题。

    写在最后的话

    从开始研究这个框架看了很多文章,收获很多,慢慢从这些文章中一点点的找到它们之间的关系,这个过程是曲折的,但也是喜悦的。后续还会更新,本篇文章只是开始,一点点皮毛。

    借鉴的文章

    iOS 图形编程总结
    iOS绘图教程
    iOS绘图框架CoreGraphics分析

    相关文章

      网友评论

        本文标题:iOS 绘图API之Core Graphics系统学习(一)

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