这三种东西:CGContextRefCGPathUIBezierPath。本质上都是一样的,都是使用Quartz来绘画。只不过把绘图操作暴露在不同的API层面上,在具体实现上,当然也会有一些细小的差别。

我们将主要使用这3个类型,绘制出同一张图片,如下,一个笑脸:

首先使用Quartz的CGPath来做这张图。很简单,首先创建用于转移坐标的Transform,然后创建一个CGMutablePathRef(属于CGPath类型)对象。接着通过两个CGPathAddEllipseInRect和一个CGPathAddArc函数来绘制Path中的两个眼睛和一个嘴,注意把CGAffineTransform的地址传进去,这样Transform才会应用。接着把这个创建好的CGPath加入到当前CGContextRef中,最后通过CGContextRef执行绘画。

代码:

- (void)viewDidLoad{    [super viewDidLoad];

    //开始图像绘图    UIGraphicsBeginImageContext(self.view.bounds.size);    //获取当前CGContextRef    CGContextRef gc = UIGraphicsGetCurrentContext();

    //创建用于转移坐标的Transform,这样我们不用按照实际显示做坐标计算    CGAffineTransform transform = CGAffineTransformMakeTranslation(50, 50);    //创建CGMutablePathRef    CGMutablePathRef path = CGPathCreateMutable();    //左眼    CGPathAddEllipseInRect(path, &transform, CGRectMake(0, 0, 20, 20));    //右眼    CGPathAddEllipseInRect(path, &transform, CGRectMake(80, 0, 20, 20));    //笑    CGPathMoveToPoint(path, &transform, 100, 50);    CGPathAddArc(path, &transform, 50, 50, 50, 0, M_PI, NO);    //将CGMutablePathRef添加到当前Context内    CGContextAddPath(gc, path);    //设置绘图属性    [[UIColor blueColor] setStroke];    CGContextSetLineWidth(gc, 2);    //执行绘画    CGContextStrokePath(gc);

    //从Context中获取图像,并显示在界面上    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();

    UIImageView *imgView = [[UIImageView alloc] initWithImage:img];    [self.view addSubview:imgView];}

接下来,我们不去使用CGPath类型的相关函数,而完全使用CGContextRef相关的函数,这些函数执行起来其实是和上面讲的的CGPath完全等价的。

这里需要注意的是,完全使用CGContextRef的话,Transform的应用需使用CGContextTranslateCTM函数。

完整代码:

- (void)viewDidLoad{    [super viewDidLoad];

    //开始图像绘图    UIGraphicsBeginImageContext(self.view.bounds.size);    //获取当前CGContextRef    CGContextRef gc = UIGraphicsGetCurrentContext();

    //使用CGContextTranslateCTM函数来转移坐标的Transform,这样我们不用按照实际显示做坐标计算    CGContextTranslateCTM(gc, 50, 50);    //左眼    CGContextAddEllipseInRect(gc, CGRectMake(0, 0, 20, 20));    //右眼    CGContextAddEllipseInRect(gc, CGRectMake(80, 0, 20, 20));    //笑    CGContextMoveToPoint(gc, 100, 50);    CGContextAddArc(gc, 50, 50, 50, 0, M_PI, NO);    //设置绘图属性    [[UIColor blueColor] setStroke];    CGContextSetLineWidth(gc, 2);    //执行绘画    CGContextStrokePath(gc);

    //从Context中获取图像,并显示在界面上    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    UIImageView *imgView = [[UIImageView alloc] initWithImage:img];    [self.view addSubview:imgView];}

同样会绘制出上面的图形。

最后我们使用UIBezierPath类型来完成上述图形,UIBezierPath很有意思,它包装了Quartz的相关API,自己存在于UIKit中,因此不是基于C的API,而是基于Objective-C对象的。那么一个非常重要的点是由于离开了Quartz绘图,所以不需要考虑Y轴翻转的问题,在画弧的时候,clockwise参数是和现实一样的,如果需要顺时针就传YES,而不是像Quartz环境下传NO的。

其次椭圆的创建需使用bezierPathWithOvalInRect方法,这里名字是Oral而不是Quartz中的Ellipse

最后注意UIBezierPathapplyTransform方法需要最后调用。

完整代码:

- (void)viewDidLoad{    [super viewDidLoad];

    //开始图像绘图    UIGraphicsBeginImageContext(self.view.bounds.size);

    //创建UIBezierPath    UIBezierPath *path = [UIBezierPath bezierPath];    //左眼    [path appendPath:[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 20, 20)]];    //右眼    [path appendPath:[UIBezierPath bezierPathWithOvalInRect:CGRectMake(80, 0, 20, 20)]];    //笑    [path moveToPoint:CGPointMake(100, 50)];    //注意这里clockwise参数是YES而不是NO,因为这里不知Quartz,不需要考虑Y轴翻转的问题    [path addArcWithCenter:CGPointMake(50, 50) radius:50 startAngle:0 endAngle:M_PI clockwise:YES];    //使用applyTransform函数来转移坐标的Transform,这样我们不用按照实际显示做坐标计算    [path applyTransform:CGAffineTransformMakeTranslation(50, 50)];    //设置绘画属性    [[UIColor blueColor] setStroke];    [path setLineWidth:2];    //执行绘画    [path stroke];

    //从Context中获取图像,并显示在界面上    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    UIImageView *imgView = [[UIImageView alloc] initWithImage:img];    [self.view addSubview:imgView];

iOS: 使用CGContextRef,CGPath和UIBezierPath来绘画的更多相关文章

  1. [ios]ios画线 使用CGContextRef,CGPath和UIBezierPath来绘画

    参考 :http://www.mgenware.com/blog/?p=493 这三种东西:CGContextRef,CGPath和UIBezierPath.本质上都是一样的,都是使用Quartz来绘 ...

  2. iOS使用Core Graphics和UIBezierPath绘画

    通过UIView的子类的- (void)drawRect:(CGRect)rect 函数可用对视图进行重新绘画: 要重新绘画可以通过Core Graphics和UIBezierPath来实现. 1.通 ...

  3. IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)

    ... 首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Con ...

  4. (转) IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)

    首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Context ...

  5. [置顶] IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)

    首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Context ...

  6. iOS绘图CGContextRef详解

    转自:http://blog.csdn.net/u014286994/article/details/51333118 /* CoreGraphics - CGContext.h */ /** Gra ...

  7. OS: 剪裁UIImage部分不规则区域

    首先,我们需要把图片展示在界面上.很简单的操作,唯一需要注意的是由于CGContextDrawImage会使用Quartz内以左下角为(0,0)点的坐标系,所以需要使用CGContextTransla ...

  8. iOS 之UIBezierPath

    代码地址如下:http://www.demodashi.com/demo/11602.html 在之前的文章中,由于用到过UIBezierPath这个类,所以这里就对这个类进行简单的记录一下,方便自己 ...

  9. iOS旋钮动画-CircleKnob

    欢迎相同喜欢动效的project师/UI设计师/产品添加我们 iOS动效特攻队–>QQ群:547897182 iOS动效特攻队–>熊熊:648070256 前段时间和群里的一个设计师配合. ...

随机推荐

  1. 定制Asp.NET 5 MVC内建身份验证机制 - 基于自建SQL Server用户/角色数据表的表单身份验证

    背景 在需要进行表单认证的Asp.NET 5 MVC项目被创建后,往往需要根据项目的实际需求做一系列的工作对MVC 5内建的身份验证机制(Asp.NET Identity)进行扩展和定制: Asp.N ...

  2. linux crontab & 每隔10秒执行一次

    linux下定时执行任务的方法  在LINUX中你应该先输入crontab -e,然后就会有个vi编辑界面,再输入0 3 * * 1 /clearigame2内容到里面 :wq 保存退出. 在LINU ...

  3. JAVA基础知识点:内存、比较和Final

    1.java是如何管理内存的 java的内存管理就是对象的分配和释放问题.(其中包括两部分) 分配:内存的分配是由程序完成的,程序员需要通过关键字new为每个对象申请内存空间(基本类型除外),所有的对 ...

  4. atomic, spinlock and mutex性能比较

    我非常好奇于不同同步原理的性能,于是对atomic, spinlock和mutex做了如下实验来比较: 1. 无同步的情况 #include <future> #include <i ...

  5. [转]ionic $state.go passed $stateParams

    本文转自:http://stackoverflow.com/questions/19516771/state-go-toparams-not-passed-to-stateparams If you ...

  6. 自定义input[type="file"]的样式

    input[type="file"]的样式在各个浏览器中的表现不尽相同: 1. chrome: 2. firefox: 3. opera: 4. ie: 5. edge: 另外,当 ...

  7. 如何为自己的项目在pycharm中设置debug?

    比方说我们的某一个项目运行需要走这个指令: (MyObject)blaxon@debian:~/Desktop/checkmato$ python checkmato/nose_plugin/plug ...

  8. HDU 5056 Boring Count --统计

    题解见官方题解,我这里只实现一下,其实官方题解好像有一点问题诶,比如 while( str[startPos] != str[i+1] ) cnt[str[startPos]]--, startPos ...

  9. 基础KMP两道

    1. HDU 1711 Number Sequence 代码: #include <iostream> #include <cstdio> #include <cstri ...

  10. 第13章 Windows内存体系结构

    13.1 Windows的虚拟地址空间安排 13.1.1虚拟地址空间的分区(即虚拟地址空间布局) 进程的地址空间划分 分区 x86 32位 Windows 3GB用户模式下的x86 32位Window ...