IOS 绘图 CoreGraphics

简介

核心绘图:
当一个视图View显示在屏幕上时,其展现给用户的样式都是经过系统绘制后显示在屏幕上的。例如,UILabel控件能够在控件所在矩形区域的中间/左侧/右侧显示文字,UIImageView可以显示一张图片,UIButton可以显示图片加文字,这些控件最终展示的效果其实都是经过绘图后才显示出来的,而绘图的过程可以由程序员自行控制。也正因为如此,我们可以去控制绘图的过程,从而可以使视图展示不同的效果。这就需要我们去学习CoreGraphics框架。

Quartz2D

CoreGraphics中最关键的部分是一个名为Quartz 2D的API集合,它包含了各种函数、数据类型以及对象,能够让大家在内存中直接绘制视图和图像。在使用CoreGraphics框架时,需要提前了解在绘图过程中涉及的几个重要概念。

画布(page)

Quartz 2D将正在进行绘制的视图视作一个虚拟的画布,在画布上用画笔画画,就必须遵循一定的规则,例如,绘制的内容是有先后顺序的,如下图所示。后画的会把之前画的覆盖掉。
在这里插入图片描述

路径(Path)

当你拿到一只画笔时,那么就能够随心所欲的在画纸上绘画,画笔移动的轨迹就是路径。如下图所示,一只粉红色的画笔绘制了两个图形,中间使用蓝色进行了填充。在UIKit框架中,有一个称为贝塞尔路径(UIBezierPath)的类专门用来设置各种样式的路径对象。
在这里插入图片描述

绘图上下文(Graphics Context)

绘图上下文,有时也称为绘图环境,绘图上下文中会保存绘图的信息和状态,并负责将图形绘制在视图上,即绘图的输出终端(Drawing Destination),Quartz提供了5种绘图的输出目标,如下图所示。例如,可以输出到窗口屏幕window,也可以输出到打印机printer,也可以保存为文件PDF等。但我们在开发中最经常使用的是layer,后续会详细介绍。
在这里插入图片描述

绘图原理

有关Quartz2D的绘图原理和我们日常生活中绘图是一致的。例如,我们拿出一张纸,以及一支笔,那么就可以使用这支笔在纸上画出各种线条(路径),线条的样式,例如:线条的粗细以及颜色,则取决于画笔;而路径则取决于绘画者的意愿。当线条或者图画之间有交叉或者覆盖时,最新绘画的内容会覆盖之前的内容。

使用Quartz2D进行图形绘制时,通常需要向图形所在的视图中添加绘图代码。比如创建一个UIView的子类,并向该类的drawRect:方法中添加Quartz函数的调用,重写系统默认的drawRect方法,相当于在系统原来的绘图基础上,再进行新的绘图。

注意一个特殊情况:UIImageView的子类不会调用drawRect方法

绘图中经常使用的方法

在使用CoreGraphics框架对视图进行绘图操作时,UIView中如下的几个方法需要程序员重点关注,这涉及到绘图的时机。

drawRect:方法:当视图每次需要进行自身重新绘制时都会调用该方法,所以如果在drawRect:方法中插入视图绘制的代码,那么这段绘图代码就会起效,从而对视图进行重绘。该方法会被系统自动调用。

  • (void)drawRect:(CGRect)rect;
    setNeedDisplay方法:当手工调用这个方法时,会调用drawRect:方法进行绘图,但该方法是异步执行的,即不是立即调用drawRect:方法进行绘图,而是在屏幕每次刷新后才会调用。
  • (void)setNeedsDisplay;

贝塞尔路径(UIBezierPath)

UIBezierPath类属于UIKit框架,主要用于绘图中设置绘图的路径。在Core Graphics中,也提供了CGPath类以及CGContext类可以用于绘图。在实际开发中,UIBezierPath类的使用比CGPath类和CGContext类要简单,所以我们重点来学习UIBezierPath类在绘图中的应用。

常用方法

UIBezierPath类主要用于创建一个路径对象,因此在UIBezierPath类中提供了创建各种类型路径的方法,例如直线路径、曲线路径等等。

实例化一个贝塞尔路径对象
+(UIBezierPath *)bezierPath;
初始化矩形路径
+(UIBezierPath *)bezierPathWithRect:(CGRect)rect;
初始化一个圆角的矩形路径
+(instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;
初始化椭圆形路径
+(UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect;
初始化弧形路径。需要传入四个参数,包括弧形的圆心点、弧度以及起始、终止角度
+(UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
设置当前绘图所在的点位,即设置画笔当前的位置
-(void)moveToPoint:(CGPoint)point;
从绘图当前点位绘制一条直线到目标点位
-(void)addLineToPoint:(CGPoint)point;
从绘图当前点位绘制一条圆弧到目标点位,弧度需要由控制点controlPoint决定
-(void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;
封闭当前的路径
-(void)closePath;
填充路径所封闭的区域
-(void)fill;
画线
-(void)stroke;

绘图方法和步骤

drawRect:方法的调用时机

drawRect:方法是UIView类定义中的方法,视图每次需要进行自身重新绘制时都会调用该方法,所以如果在drawRect:方法中插入绘图代码,那么这段绘图代码就会起效,从而对视图进行重绘。

drawRect:方法主要在如下几个情形下会被调用。

当视图第一次显示到屏幕之前;
当调用视图的setNeedDisplay或者setNeedDisplayInRect:方法,通知重新绘图时。
调用sizeToFit方法后,会调用drawRect:方法。

常见的绘图步骤

当在drawRect:方法中进行绘图时,一般会遵循如下的步骤进行:

获得图形上下文(取得画布),需要调用UIGraphicsGetCurrentContext()函数;
设置路径(绘图),通常使用贝塞尔路径;
设置绘图上下文的属性与状态,如是否填充,填充颜色等等;
添加路径到上下文,调用CGContextAddPath()函数;
渲染上下文,调用CGContextStrokePath()函数,输出绘图图像到屏幕。

绘图示例

绘制一个封闭的三角形,该三角形边线的颜色是红色,线宽是3px,填充颜色是黄色。

-(void)myDrawTriangle{
    //1.获取绘图上下文
    CGContextRef context=UIGraphicsGetCurrentContext();
    
    //2.设置绘图路径
    //2.1创建路径
    UIBezierPath *path=[UIBezierPath bezierPath];
    //2.2创建起始点
    CGPoint startPoint=CGPointMake(5, 5);
    CGPoint secondPoint=CGPointMake(50, 95);
    CGPoint thirdPoint=CGPointMake(95, 5);
    //2.3画线
    [path moveToPoint:startPoint];
    [path addLineToPoint:secondPoint];
    [path addLineToPoint:thirdPoint];
    //2.4设置线的属性
    [[UIColor redColor] setStroke];
    [[UIColor yellowColor]setFill];
    [path fill];
    
    //3.设置边线的宽度
    CGContextSetLineWidth(context, 3.0);
    
    //4.添加路径到上下文
    CGContextAddPath(context, path.CGPath);
    
    //5.渲染上下文
    CGContextStrokePath(context);
}

常见图像的绘制方法

绘图的样式都是由路径来决定的。
创建继承自UIView的自定义类,在类中重写drawRect:方法,在该方法中添加绘图相关的代码。

绘制直线

假如需要绘制直线,需要绘制一个贝塞尔路径对象,并指定路径的开始点和结束点,然后在开始点和结束点之间加一条线。
使用自定义的UI类,要设置背景和尺寸,不然看不出来。

-(void)myDrawLine{
    //重写绘图方法
    //获取上下文/环境
    CGContextRef context=UIGraphicsGetCurrentContext();
    //设置画笔宽度
    CGContextSetLineWidth(context, 3.0);
    //设置画笔颜色
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    
    //绘图
    //创建绘图路径
    UIBezierPath *path=[UIBezierPath bezierPath];
    //设置起始点
    [path moveToPoint:CGPointZero];
    [path addLineToPoint:CGPointMake(200, 200)];
    //添加到上下文
    CGContextAddPath(context, path.CGPath);
    //渲染上下文
    CGContextStrokePath(context);
}

绘制矩形

-(void)myDrawRect{
    //获取上下文/环境
    CGContextRef context=UIGraphicsGetCurrentContext();
    //设置画笔宽度
    CGContextSetLineWidth(context, 3.0);
    //设置画笔颜色
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    //绘图
    //设置矩形的位置和大小
    CGRect myrect=CGRectMake(50, 50, 100, 100);
    //创建绘图路径
    UIBezierPath *path=[UIBezierPath bezierPathWithRect:myrect];
    [[UIColor yellowColor]setFill];
    [path fill];
    //添加到上下文
    CGContextAddPath(context, path.CGPath);
    //渲染上下文
    CGContextStrokePath(context);
}

绘制圆形/椭圆形

通过矩形的框,创建一个椭圆形。当矩形是正方形,得到的就是圆形。

-(void)myDrawEllipse{
    //获取上下文/环境
    CGContextRef context=UIGraphicsGetCurrentContext();
    //设置画笔宽度
    CGContextSetLineWidth(context, 3.0);
    //设置画笔颜色
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    //绘图
    //设置矩形的位置和大小
    CGRect myrect=CGRectMake(50, 50, 200, 100);
    //创建绘图路径
    UIBezierPath *path=[UIBezierPath bezierPathWithOvalInRect:myrect];
    [[UIColor yellowColor]setFill];
    [path fill];
    //添加到上下文
    CGContextAddPath(context, path.CGPath);
    //渲染上下文
    CGContextStrokePath(context);
}

在这里插入图片描述
代码:https://github.com/ShaeZhuJiu/CoreGraphics_base.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值