您的位置:首页 > 移动开发 > IOS开发

iOS——Quartz2D(二维图形绘制)

2016-08-31 00:00 232 查看

一、Quartz2D 基本概念和在iOS开发中的价值

1.1 Quartz2D 基本概念

Quartz 2D是一个二维图形绘制引擎,支持ios环境和Mac OS X环境。我们可以使用Quartz 2D API来实现许多功能如基本路径的绘制、透明度、描影、绘制阴影、透明层、颜色管理、反锯齿、PDF文档生成和PDF元数据访问。在需要的时候,Quartz 2D 还可以借助图形硬件的功能。在Mac OS X中,Quartz 2D可以与其它图形图像技术混合使用,如Core Image、Core Video、 OpenGL、QuickTime。例如,通过使用 QuickTime的GraphicsImportCreateCGImage函数,可以用 Quartz从一个 QuickTime图形导入器中创建一个图像。

1.2 Quartz2DiOS开发中的价值

为了便于搭建美观的UI界面,iOS提供了UIKit框架,里面有各种各样的UI控件,比如:

UILabel:显示文字;

UIImageView:显示图片;

UIButton:同时显示图片和文字(能点击);

利用UIKit框架提供的控件,拼拼凑凑,能搭建和现实一些简单、常见的UI界面。

但是,有些UI界面极其复杂、而且比较个性化,用普通的UI控件无法实现,这时可以利用Quartz2D技术将控件内部的结构画出来,自定义控件的样子。其实,iOS中大部分控件的内容都是通过Quartz2D画出来的。因此,Quartz2DiOS开发中很重要的一个价值是:自定义view(自定义UI控件)。

二、UIBezierPath 和 Core Graphics

OS系统本身提供了两套绘图的框架,即UIBezierPathCore Graphics。而前者所属UIKit,其实是对Core Graphics框架关于path的进一步封装,所以使用起来比较简单。但是毕竟Core Graphics更接近底层,所以它更加强大。

2.1 UIBezierPath

可以创建基于矢量的路径,例如椭圆或者矩形,或者有多个直线和曲线段组成的形状。

使用UIBezierPath,你只能在当前上下文中绘图,所以如果你当前处于UIGraphicsBeginImageContextWithOptions函数或drawRect:方法中,你就可以直接使用UIKit提供的方法进行绘图。如果你持有一个context:参数,那么使用UIKit提供的方法之前,必须将该上下文参数转化为当前上下文。幸运的是,调用UIGraphicsPushContext 函数可以方便的将context:参数转化为当前上下文,记住最后别忘了调用UIGraphicsPopContext函数恢复上下文环境。

我们一般使用UIBezierPath都是在重写的drawRecrt方法这种情形。其绘图的步骤是这样的:

1.重写drawRect方法。但不需要我们自己获取当前上下文context;

2.创建相应图形的UIBezierPath对象,并设置一些修饰属性;

3.渲染,完成绘制。

// 重写drawRect方法
- (void)drawRect:(CGRect)rect
{
// 创建图形相应的UIBezierPath对象
UIBezierPath* Path = [UIBezierPath bezierPathWithRect:CGRectMake(20, 20, 100, 50)];
// 设置一些修饰属性

// 设置线条宽度
[path setLineWidth:10];
//设置线头的样式:三种样式,kCGLineCapButt, kCGLineCapRound, kCGLineCapSquare
[Path.lineCapStyle = kCGLineCapRound];
//设置线条连接点的样式:kCGLineJoinMiter, kCGLineJoinRound,kCGLineJoinBevel
[Path.lineJoinStyle = kCGLineCapRound];
// 设置描边的颜色
[[UIColor redColor] setStroke];
[[UIColor whiteColor] setFill];

// 渲染,绘制(描边)
[Path stroke];
//绘制(内部填充)
[path fill];

}


2.2 Core Graphics

这是一个绘图专用的API族,它经常被称为QuartZ或QuartZ 2D。Core Graphics是iOS上所有绘图功能的基石,包括UIKit。

要搞清楚Core Graphics就要搞清楚下面几个问题:

1.绘图需要 CGContextRef

CGContext又叫图形上下文,相当于一块画布,以堆栈形式存放,只有在当前context上绘图才有效。iOS有分多种图形上下文,其中UIView自带提供的在drawRect:方法中通过UIGraphicsGetCurrentContext获取,还有专门为图片处理的context,UIGraphicsBeginImageContext函数生成,还有pdf的context等等。

2.怎么拿到context?

第一种方法是利用cocoa为你生成的图形上下文。当你子类化了一个UIView并实现了自己的drawRect:方法后,一旦
drawRect:
方法被调用,Cocoa就会为你创建一个图形上下文,此时你对图形上下文的所有绘图操作都会显示在UIView上。

第二种方法就是创建一个图片类型的上下文。调用
UIGraphicsBeginImageContextWithOptions
函数就可获得用来处理图片的图形上下文。利用该上下文,你就可以在其上进行绘图,并生成图片。调用
UIGraphicsGetImageFromCurrentImageContext
函数可从当前上下文中获取一个UIImage对象。记住在你所有的绘图操作后别忘了调用
UIGraphicsEndImageContext
函数关闭图形上下文。

2.3 绘图上下文相关函数

UIGraphicsGetCurrentContext()
: 获取当前绘图上下文,绘图前的第一步,因为所有的绘图都是在上下文完成的,可以理解为获取当前绘图的“画布”。

CGContextSaveGState()
: 保存上下文状态,这个函数的作用是将当前图形状态推入堆栈。之后,您对图形状态所做的修改会影响随后的描画操作,但不影响存储在堆栈中的拷贝。

CGContextRestoreGState()
: 恢复上下文状态,通过这个函数把堆栈顶部的状态弹出,返回到之前的图形状态。和CGContextSaveGState()配对使用。

CGContextSaveGState()和CGContextRestoreGState()使用举例:整个绘图都是红色,但是中间需要有个图是灰色,这种场景就可以使用这两个函数处理了。

绘图路径相关函数
CGContextMoveToPoint()
: 定位到某个点
CGContextAddLineToPoint()
: 画线,添加一条直线到一个点
CGContextAddRect()
: 画矩形
CGContextAddEllipseInRect()
: 内切圆或者椭圆
CGContextAddQuadCurveToPoint()
: 一个控制点的贝塞尔曲线
CGContextAddCurveToPoint()
: 两个控制点的贝塞尔曲线
CGContextAddArc()
: 画曲线
CGContextSetLineDash()
: 画虚线
CGContextAddPath()
: 画指定的路劲
CGContextClosePath()
: 闭合当前路径

绘图设置相关函数
CGContextSetLineWidth()
: 设置线条的宽度
CGContextSetStrokeColorWithColor()
: 设置线条的颜色(使用UIColor颜色)
CGContextSetStrokeColor()
: 设置线条颜色(三色值和透明度)
CGContextSetRGBStrokeColor()
: 设置线条颜色(RGB值)
CGContextSetFillColor()
: 设置图形填充颜色(三色值和透明度)
CGContextSetFillColorWithColor()
: 设置填充颜色(UIColor值)
CGContextSetRGBFillColor()
:设置填充颜色(RGB值)
CGContextSetAlaha()
: 设置透明度
CGContextSetShouldAntialias()
: 是否开启抗锯齿
CGContextSetLineCap()
: 设置直线端点的样式()
CGContextSetLineJoin()
: 设置直线连接点的样式
CGContextSetShadow()
: 设置阴影(尺寸和模糊度)
CGContextSetShadowWithColor()
: 设置阴影和阴影颜色

图形填充相关函数
CGContextFillRect()
: 填充一个矩形
CGContextStrokePath()
: 描边
CGContextFillPath()
: 只填充不描边
CGContextEOFillPath()
: 使用奇偶规则填充
CGContextDrawPath()
: 绘制路径(可以选择填充的样式)

使用Core Graphics绘图

第一步:获取当前绘图上下文,相当于创建“画布”

CGContextRef ctx = UIGraphicsGetCurrentContext();


第二步:设置要绘制的图形

绘图路径
在画线的时候,方法的内部默认创建一个path。它把路径都放到了path里面去。
代码示例:
绘制一条直线的代码:

//直线
// 创建一条路径对象
UIBezierPath *path = [UIBezierPath bezierPath];
// 将画笔移动到某个点
[path moveToPoint:CGPointMake(20, 50)];
// 绘制一条直线到某个点
[path addLineToPoint:CGPointMake(300, 50)];
[path addLineToPoint:CGPointMake(160, 200)];
// [path addLineToPoint:CGPointMake(20, 50)];
// 闭合路径
[path closePath];

绘制画矩形,圆角矩形,内切的椭圆的代码:

// 画矩形
// UIBezierPath *path = [UIBezierPath bezierPathWithRect:rect];

// 圆角矩形
// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:20];

// 内切的椭圆、圆形
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];

绘制画弧线的代码:

#pragma mark - 画弧线
- (void)drawArc {
CGPoint center = self.center;
/**
Center: 圆心
radius: 半径
startAngle: 起始弧度
endAngle: 终点弧度
clockwise:是否顺时针
**/
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:150 startAngle:0 endAngle: M_PI_2 clockwise:YES];

path.lineWidth = 5;
[path addLineToPoint:center];
[path closePath];

[[UIColor redColor] setStroke];
[[UIColor whiteColor] setFill];

[path stroke];
[path fill];
}


绘制贝赛尔曲线的代码:

[path moveToPoint:beginPoint];
//一个控制点的贝塞尔曲线
[path addQuadCurveToPoint:endPoint controlPoint:controlPoint];

CGPoint beginPoint_1 = CGPointMake(50, 300);
CGPoint endPoint_1 = CGPointMake(150, 300);
CGPoint controlPoint_1 = CGPointMake(75, 400);
CGPoint controlPoint_2 = CGPointMake(125, 200);

[path moveToPoint:beginPoint_1];
//两个控制点的贝塞尔曲线
[path addCurveToPoint:endPoint_1 controlPoint1:controlPoint_1 controlPoint2:controlPoint_2];

//拼接两条路径
UIBezierPath *subPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(170, 300, 200, 200)];
[path appendPath:subPath];

//移除所有的路径
// [path removeAllPoints];

[path stroke];
}


绘制画波线的代码:

// 画波线
- (void)drawBezierPaths {

UIBezierPath *path = [UIBezierPath bezierPath];
[[UIColor redColor] setStroke];
path.lineWidth = 3;

// 当前视图的宽高
CGFloat screenWidth = CGRectGetWidth(self.bounds);
CGFloat screenHeight = CGRectGetHeight(self.bounds);
// 每一个曲线的宽度
CGFloat width = screenWidth / 10;

for (int i = 0; i < 10; i++) {
// 控制点的Y坐标
CGFloat controlPoint_Y = 0;
if (i % 2 == 0) {
controlPoint_Y = screenHeight / 2 - 100;
} else {
controlPoint_Y = screenHeight / 2 + 100;
}

CGPoint beginPoint = CGPointMake(i * width, screenHeight / 2);
CGPoint endPoint = CGPointMake(beginPoint.x + width, screenHeight / 2);
CGPoint controlPoint = CGPointMake((width / 2)+ (i * width), controlPoint_Y);

[path moveToPoint:beginPoint];
[path addQuadCurveToPoint:endPoint controlPoint:controlPoint];
}

[path stroke];
}


总结

Core Graphics
是iOS绘图的基础框架,UIKit是对它的一个封装,以使绘制常见图形更加方便,比如
UIBezierPath
就可以直接绘制
圆角矩形,
Core Graphics
要通过不同的方法配合使用才能实现,iOS应用开发中的大部分绘制需求应该都可以通过
UIKit
的绘制方法实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息