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

iOS开发之Quartz 2D绘图技术(一)

2016-04-08 14:47 375 查看
什么是Quartz2D?
Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统
Quartz 2D的API是纯C语言的来自于Core Graphics框架数据类型和函数都是以CG为前缀

CGContextRef\CGPathRef\CGContextStrokePath(ctx)

Quartz 2D能完成的工作
绘制图形 : 线条\三角形\矩形\圆\弧等
绘制文字
绘制\生成图片(图像)
读取\生成PDF
截图\裁剪图片
自定义UI控件
......

Quartz2D在iOS开发中的价值?
为了便于搭建美观的UI界面,iOS提供了UIKit框架,里面有各种各样的UI控件
UILabel:显示文字
UIImageView:显示图片
UIButton:同时显示图片和文字(能点击)
......
1>利用UIKit框架提供的控件,拼拼凑凑,能搭建和现实一些简单、常见的UI界面
2>但是,有些UI界面极其复杂、而且比较个性化,用普通的UI控件无法实现,这时可以利用Quartz2D技术将控件内部的结构画出来,自定义控件的样子
3>其实,iOS中大部分控件的内容都是通过Quartz2D画出来的
4>因此,Quartz2D在iOS开发中很重要的一个价值是:自定义view(自定义UI控件)
5>那么废话不多说,直接上

图形上下文
图形上下文(Graphics Context):是一个CGContextRef类型的数据
图形上下文的作用
保存绘图信息、绘图状态
决定绘制的输出目标(绘制到什么地方去?)

(输出目标可以是PDF文件、Bitmap或者显示器的窗口上)
相同的一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上

//

// ViewController.h

// Quartz2D

//

// Created by 周昭 on 16/4/8.

// Copyright © 2016年 Jordan Zhou. All rights reserved.

//

#import <UIKit/UIKit.h>

@interface ViewController :
UIViewController

@end

//

// ViewController.m

// Quartz2D

//

// Created by 周昭 on 16/4/8.

// Copyright © 2016年 Jordan Zhou. All rights reserved.

//

#import "ViewController.h"

#import "ZZQuartz2D.h"

@interface
ViewController ()

@property (nonatomic,
weak) ZZQuartz2D *drawViw;

@end

@implementation ViewController

- (void)viewDidLoad {

[super
viewDidLoad];

//
加载绘图view

[self
setUpQuartz2DView];

//
重绘slider

[self
setUpSlider];

}

/**

* 添加绘图view

*/

- (void)setUpQuartz2DView

{

ZZQuartz2D *drawViw = [[ZZQuartz2D
alloc] initWithFrame:[UIScreen
mainScreen].bounds];

drawViw.backgroundColor = [UIColor
whiteColor];

[self.view
addSubview:drawViw];

self.drawViw = drawViw;

}

/**

* 创建slider

*/

- (void)setUpSlider

{

UISlider *slider = [[UISlider
alloc] init];

slider.minimumValue =
0;

slider.maximumValue =
100;

CGFloat sliderX =
self.view.frame.size.width *
0.5;

CGFloat sliderY =
self.view.frame.size.height *
0.7;

CGFloat sliderW =
self.view.frame.size.width *
0.8;

CGFloat sliderH =
20;

slider.center =
CGPointMake(sliderX, sliderY);

slider.bounds =
CGRectMake(0,
0, sliderW, sliderH);

[self.view
addSubview:slider];

//
类似于UISlider\UISwitch
这样的控件事件改变是其值的改变

[slider addTarget:self
action:@selector(sizeChange:)
forControlEvents:UIControlEventValueChanged];

}

/**

* 根据set方法来赋值并且在内部调用 setNeedsDisplay
重绘的方法

*/

- (void)sizeChange:(UISlider *)slider

{

self.drawViw.radius = slider.value;

}

@end

//

// ZZQuartz2D.h

// Quartz2D

//

// Created by 周昭 on 16/4/8.

// Copyright © 2016年 Jordan Zhou. All rights reserved.

//

#import <UIKit/UIKit.h>

@interface ZZQuartz2D :
UIView

/**

* 圆的半径

*/

@property (nonatomic,
assign) float radius;

@end

//

// ZZQuartz2D.m

// Quartz2D

//

// Created by 周昭 on 16/4/8.

// Copyright © 2016年 Jordan Zhou. All rights reserved.

//

#import "ZZQuartz2D.h"

@interface ZZQuartz2D()

@property (nonatomic,
assign) CGFloat snowY;

@end

@implementation ZZQuartz2D

/**

* 重写set方法

*/

- (void)setRadius:(float)radius

{

_radius = radius;

// 重绘的方法只能是自己调用

[self
setNeedsDisplay];

}

/**

* 当你创建view的时候这个方法就会自动创建可见这个方法的重要性

*/

- (void)drawRect:(CGRect)rect {

#warning 这个方法只会调一次走一次

/*

drawLine(); 画线

graphicsContextStack();
图形上下文栈(重点:这个原理流程见分析思路)

draw4Rect(); 画四边形

drawTriangle();
画三角形

drawArc(); 画圆弧

drawCircle(); 画圆

drawCircle4(); 画1/4圆

drawImage(); 画图片

drawText(); 画文字

matrixOperation();
矩阵操作

[self reDrawCircle];
重绘(刷帧)

[self drawSnowAnimation];
画出下雪的效果

*/

}

/**

* 画线\多条线\区分线段样式

*/

void drawLine()

{

// 1.获得图形上下文

CGContextRef ctx =
UIGraphicsGetCurrentContext();

// 2.拼接图形(路径)

CGContextSetLineWidth(ctx,
10);

// 设置线段头尾部的样式

CGContextSetLineCap(ctx,
kCGLineCapRound);

// 设置线段转折点的样式

CGContextSetLineJoin(ctx,
kCGLineJoinRound);

#pragma mark ---- 这里要求区分画出俩条线它们的属性即
线宽\颜色\转角点不一样
这是一种做法 重新设置属性然后多次渲染

/**
第1根线段 **/

//
设置颜色

CGContextSetRGBStrokeColor(ctx,
1, 0,
0, 1);

//
设置一个起点

CGContextMoveToPoint(ctx,
10,
10);

//
添加一条线段到(100, 100)

CGContextAddLineToPoint(ctx,
100,
100);

//
渲染一次

CGContextStrokePath(ctx);

/**
第2根线段 **/

//
设置颜色

CGContextSetRGBStrokeColor(ctx,
0, 0,
1, 1);

//
设置一个起点

CGContextMoveToPoint(ctx,
200,
190);

//
添加一条线段到(150, 40)

CGContextAddLineToPoint(ctx,
130,
50);

CGContextAddLineToPoint(ctx,
100,
70);

// 3.渲染显示到view上面

CGContextStrokePath(ctx);

}

/**

* 图形上下文栈

*/

void graphicsContextStack()

{

// 1.获得上下文

CGContextRef ctx =
UIGraphicsGetCurrentContext();

//
将ctx拷贝一份放到栈中

CGContextSaveGState(ctx);

//
设置绘图状态

CGContextSetLineWidth(ctx,
10);

[[UIColor redColor]
set];

CGContextSetLineCap(ctx,
kCGLineCapRound);

//
第1根线

CGContextMoveToPoint(ctx,
50,
50);

CGContextAddLineToPoint(ctx,
120,
190);

CGContextStrokePath(ctx);

// 将栈顶的上下文出栈,替换当前的上下文

CGContextRestoreGState(ctx);

//
第2根线

CGContextMoveToPoint(ctx,
10,
70);

CGContextAddLineToPoint(ctx,
220,
290);

CGContextStrokePath(ctx);

// CGContextDrawPath(ctx, kCGPathStroke);
这个相比传递参数还多一点为什么不记住简单?

}

/**

* 画四边形

*/

void draw4Rect()

{

// 1.获得上下文

CGContextRef ctx =
UIGraphicsGetCurrentContext();

// 2.画矩形

CGContextAddRect(ctx,
CGRectMake(50,
50,
150, 100));

// set :
同时设置为实心和空心颜色

// setStroke :
设置空心颜色

// setFill :
设置实心颜色

[[UIColor
whiteColor] set];

// CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);

// 3.绘制图形

CGContextFillPath(ctx);

}

/**

* 画三角形

*/

void drawTriangle()

{

// 1.获得上下文

CGContextRef ctx =
UIGraphicsGetCurrentContext();

// 2.画三角形

CGContextMoveToPoint(ctx,
0, 0);

CGContextAddLineToPoint(ctx,
100,
100);

CGContextAddLineToPoint(ctx,
150,
80);

// 关闭路径(连接起点和最后一个点)

CGContextClosePath(ctx);
// CGContextAddLineToPoint(ctx, 0, 0);
在连回去也是ok的

CGContextSetRGBStrokeColor(ctx,
0, 1,
0, 1);

// 3.绘制图形

CGContextStrokePath(ctx);

}

/**

* 画圆弧

*/

void drawArc()

{

// 1.获得上下文

CGContextRef ctx =
UIGraphicsGetCurrentContext();

// 2.画圆弧

// x\y :
圆心

// radius :
半径

// startAngle :
开始角度

// endAngle :
结束角度

// clockwise :
圆弧的伸展方向(0:顺时针, 1:逆时针)

CGContextAddArc(ctx,
100, 100, 50,
M_PI_2, M_PI,
0);

// 3.显示所绘制的东西

CGContextFillPath(ctx);

}

/**

* 画圆

*/

void drawCircle()

{

// 1.获得上下文

CGContextRef ctx =
UIGraphicsGetCurrentContext();

// 2.画圆

CGContextAddEllipseInRect(ctx,
CGRectMake(50,
10,
100, 100));

CGContextSetLineWidth(ctx,
10);

// 3.显示所绘制的东西

CGContextStrokePath(ctx);

}

/**

* 画1/4圆

*/

void drawCircle4()

{

// 1.获得上下文

CGContextRef ctx =
UIGraphicsGetCurrentContext();

// 2.画1/4圆

CGContextMoveToPoint(ctx,
100,
100);

CGContextAddLineToPoint(ctx,
100,
150);

CGContextAddArc(ctx,
100, 100, 50, -M_PI_2,
M_PI, 1);

CGContextClosePath(ctx);

[[UIColor redColor]
set];

// 3.显示所绘制的东西

CGContextFillPath(ctx);

}

/**

* 画图片

*/

void drawImage()

{

// 1.取得图片

UIImage *image = [UIImage
imageNamed:@"jordan"];

// 2.画

/*

[image drawAtPoint:CGPointMake(50, 50)]; //
画在那个点

[image drawInRect:CGRectMake(0, 0, 150, 150)]; //
画在一个矩形框内

*/

[image drawAsPatternInRect:CGRectMake(0,
0, 200,
200)];
// 平铺

// 3.画文字

NSString *str =
@"为xxx所画";

[str drawInRect:CGRectMake(0,
180,
100, 30)
withAttributes:nil];

}

/**

* 画文字

*/

void drawText()

{

// 1.获得上下文

CGContextRef ctx =
UIGraphicsGetCurrentContext();

// 2.画矩形

CGRect cubeRect =
CGRectMake(50,
50, 100, 100);

CGContextAddRect(ctx, cubeRect);

// 3.显示所绘制的东西

CGContextFillPath(ctx);

// 4.画文字

NSString *str =
@"My mood is so bad!!!";

// [str drawAtPoint:CGPointZero withAttributes:nil];

NSMutableDictionary *attrs = [NSMutableDictionary
dictionary];

// NSForegroundColorAttributeName :
文字颜色

// NSFontAttributeName :
字体

attrs[NSForegroundColorAttributeName] = [UIColor
redColor];

attrs[NSFontAttributeName] = [UIFont
systemFontOfSize:50];

[str drawInRect:cubeRect
withAttributes:attrs];

}

/**

* 矩阵操作

*/

void matrixOperation()

{

// 1.获得上下文

CGContextRef ctx =
UIGraphicsGetCurrentContext();

//
将ctx拷贝一份放到栈中

CGContextSaveGState(ctx);

CGContextRotateCTM(ctx,
M_PI_4 *
0.3);

CGContextScaleCTM(ctx,
0.5,
0.5);

CGContextTranslateCTM(ctx,
0, 150);

CGContextAddRect(ctx,
CGRectMake(10,
10,
50, 50));

CGContextStrokePath(ctx);

CGContextRestoreGState(ctx);

CGContextAddEllipseInRect(ctx,
CGRectMake(100,
100,
100, 100));

CGContextMoveToPoint(ctx,
100,
100);

CGContextAddLineToPoint(ctx,
200,
250);

//
矩阵操作

// CGContextScaleCTM(ctx, 0.5, 0.5);

CGContextStrokePath(ctx);

}

/**

* 裁剪操作

*/

void clipCirle()

{

CGContextRef ctx =
UIGraphicsGetCurrentContext();

CGContextSaveGState(ctx);

// 0.画圆

CGContextAddEllipseInRect(ctx,
CGRectMake(100,
100,
50, 50));

//
裁剪

CGContextClip(ctx);

CGContextFillPath(ctx);

// 1.显示图片

UIImage *image = [UIImage
imageNamed:@"jordan"];

[image drawAtPoint:CGPointMake(100,
100)];

CGContextRestoreGState(ctx);

CGContextAddRect(ctx,
CGRectMake(0,
0, 50,
50));

CGContextFillPath(ctx);

}

/**

* 重绘(刷帧)

*/

- (void)reDrawCircle

{

CGContextRef ctx =
UIGraphicsGetCurrentContext();

CGContextAddArc(ctx,
125, 125, self.radius,
0, M_PI *
2, 0);

CGContextFillPath(ctx);

}

/**

* 画出下雪的动画

*/

- (void)drawSnowAnimation

{

//
调用的比较频繁用 CADisplayLink @selector
调用系统自带的方法就够不要自己写

CADisplayLink *link = [CADisplayLink
displayLinkWithTarget:self
selector:@selector(setNeedsDisplay)];

[link addToRunLoop:[NSRunLoop
mainRunLoop] forMode:NSDefaultRunLoopMode];

// 这个是用定时器调用

// [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(setNeedsDisplay) userInfo:nil repeats:YES];

self.snowY+=5;

if (self.snowY >=
self.frame.size.height) {

self.snowY = -100;

}

UIImage *image = [UIImage
imageNamed:@"jordan"];

[image drawAtPoint:CGPointMake(0,
self.snowY)];

}

#pragma mark ---- 那么在这里最后也给同学们推荐一个Quartz 2D绘图的博客写的更加详细 有同学需要做K线图\绘图\制表的可以借鉴
// http://donbe.blog.163.com

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: