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

IOS:Quartz2D

2013-12-23 17:07 351 查看
理论基础:

Core Graphics(核心图层)框架是一组基于C的API,可以用于一切绘图操作!

Quartz2D API 是Core Graphics框架的一部分因此在Quartz2D中很多的数据类型和方法都是以CG开头的

Quartz2D是一个二维图形绘制引擎,主要用来绘制二维图形,可以实现很多功能如:基于路径的绘图、透明度、阴影、颜色、管理、反锯齿、PDF文档的生成和PDF元数据访问等

Quartz2D与分辨率和设备无关意味着代码不管是在打印机还是其他设备都可以直接运行

在Xcode新建好项目,运用时不必引入Quartz2D框架的头文件这是因为:项目中已经包含了#import <UIKit/UIKit.h>这个文件,而UIKit依赖于Core
Graphics,那么Core Graphics框架会被自动引入,即UIKit内部已经包含了Core Graphics框架的主头文件,为了让开发者不必接触底层的Core Graphics的C接口UIKit内部已经封装了Core Graphics的一些API,但是有时候也可以直接利用Core
Graphics的C接口。所以当使用UIKit创建按钮、标签或者其他UIView的子类时,UIKit会用Core Graphics将这些元素绘制在屏幕上。此外UIEvent(UIKit中的事件处理类)也会使用Core Graphics用来帮助确定触摸事件在屏幕上所处的位置

理论中几个比较重要的概念:

1、图形:以路径的方式描述的一个形状。就是个形状比如圆、长方形等几何图形或者非几何图形只不过这里成为路径

2、图像:简单的说就是很多的像素点逐一绘制在屏幕上所呈现的路径

可以发现:图形和图像很类似,那么做个简单的对比吧

图形:是通过代码绘制路径的方式实现,因此可以是任何图形包括复杂图形。而且在绘制简单图形时效率高于图像。现在主要研究的就是图形的绘制

图像:可借助如PS、Adobe等三方工具,可以预先绘制并以文件形式保存。官方建议PNG格式的图像

绘图思路:

首先应该是在UIView中,然后在UIView的上下文中就可绘图.因此在ios中如果想在屏幕上绘图,需要创建一个UIView对象,并实现它的drawRect:方法,此方法在UIView显示在屏幕上及UIView内部的内容需要更新时调用,而且一个UIView需要被刷新或者重绘也会被调用(重绘时应该调用setNeedsDisplay而不能直接调用drawRect:方法,因为setNeedsDisplay会自动调用drawRect:方法)

执行方法后UIView对象自动配置绘图环境然后执行绘图操作

在配置的时候UIView对象会对绘图环境创建一个Graphics Context.通过调用UIGraphicsGetCurrentContext()方法获取当前的Graphics Context

Graphics Context是一个数据类型(CGContextRef),封装了Quartz绘图制图到输出设备的信息

Quartz2D中所有的对象都是绘制到一个Graphics Context中,不同的设备有不同的Graphics Context,一个Graphics Context表示一个绘制目标,它包含绘制系统用于完成绘制指令的绘制参数和设备相关信息

如何绘图——-

要绘图首先要理解几个概念:

1、Quartz2D 坐标系

默认的坐标(0,0)是左下角在ios中,运用UIGraphicsGetCurrentContext方法返回的图形将上下文的坐标原点修改到左上角(即沿着Y值从上到下增大,X值从左到右增大)

有时候需要修改坐标系来达到某些效果,比如屏幕的旋转。因此屏幕的旋转只不过是对上下文中的坐标系的操作而已。

操作坐标系的方法有:

(1)CGContextRotateCTM(CGContextRef c,CGFloat angle) 方法可以相对原点旋转上下文坐标系

(2)CGContextTranslateCTM(CGContextRef c,CGFloat x,CGFloat y) 方法可以相对原点平移上下文坐标系

(3)CGContexScaleCTM(CGContextRef c,CGFloat x,CGFloat y) 方法可以缩放上下文坐标系

注意:

转换坐标系前,使用CGContextSaveGState(CGContextRef c) 保存当前上下文状态

转换坐标系后,使用CGContextRestoreGSate(CGContextRef c) 恢复之前保存的上下文状态

2、绘图顺序

3、UIView的drawRect:方法是在UIViewController的loadView和viewDidLoad两个方法之后调用的.如果UIView初始化时没有设置CGRectdrawRect:方法不会被调用。如果设置UIView的contentModel属性值为UIViewContentModeRedraw那么将在每次更改frame时自动调用drawRect:方法。如果使用UIView绘图,那么只能在drawRect:方法中获取相应的CGContextRef并绘图,而在其他方法中获取的CGContextRef不能用于绘图

4、Quartz2D 的内存管理

使用含有“Create“或者”Copy“的函数创建的对象,使用完毕后必须释放否则导致内存泄漏,反之则不用释放。如果retain了一个对象,不再使用需要将其release掉。可以使用Quartz2D的函数来指定retain和release一个对象。例如,如果创建了一个CGColorSpace对象则使用CGColorSpaceRetain和CGColorSpaceRelease来retain和release对象。也可以使用Core
Foundation的CFRetain和CFRelease. 一定不能传递NULL值给这些函数

Quartz 2D绘图的基本步骤:

1、获取与视图相关的上下文对象

- UIGraphicsGetCurrentContext

2、创建及设置路径(path)

(1)创建路径

(2)设置路径起点

(3)增加路径内容

3、将路径添加到上下文

4、设置上下文属性

- 比如:边线颜色、填充颜色、线宽。。。

5、绘制路径

6、释放路径

最基本的绘图:

绘制直线以及其他常见的几何图形

首先建立单视图的项目,然后添加一个继承自UIView的类myView,并在根视图上添加该类的对象:

在[b]myView.h文件中:[/b]

#import <UIKit/UIKit.h>

@interface myView :UIView

{

//三角形三个点的数组
CGPoint firstPoint;

CGPoint secondPoint;

CGPoint thirdPoint;

NSMutableArray *pointArray;
}

//存储点的数组

@property(retain,nonatomic)NSMutableArray *points;

//上下文

@property(assign,nonatomic)CGContextRef conext;

@end

在myView.m文件中:

#import "myView.h"

@implementation myView

- (id)initWithFrame:(CGRect)frame
{
self = [superinitWithFrame:frame];

if(self)
{

self.backgroundColor = [UIColorwhiteColor];

pointArray = [[NSMutableArrayalloc]initWithCapacity:3];
}

return
self;

}

//自动加载该方法
- (void)drawRect:(CGRect)rect
{

self.conext =UIGraphicsGetCurrentContext();

[selfdrawString:nil];

[selfcolorComents:nil];

[selfdrawImage:nil];

[selfdrawMyGraph:nil];

[selfdrawMyLine:CGPointMake(20,300)];

[selfdrawRound:nil];

CGContextRef context =UIGraphicsGetCurrentContext();

CGPoint addLines[] = {firstPoint,secondPoint,thirdPoint,firstPoint};

CGContextAddLines(context, addLines,
sizeof(addLines)/sizeof(addLines[0]));

CGContextStrokePath(context);

}

//通过触摸方法进行操作
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{

//获取触摸对象
UITouch *touch = [touches
anyObject];

//当前触摸点
CGPoint point = [touch
locationInView:self];

[pointArrayaddObject:[NSValuevalueWithCGPoint:point]];

//只存储3个触摸点
if(pointArray.count >3)
{

[pointArrayremoveObjectAtIndex:0];
}

//如果刚好存储三个点,就获取三个CGPoint的值,涉及到一个转换,NSArray只能存放对象
if(pointArray.count ==3)
{

firstPoint = [[pointArrayobjectAtIndex:0]CGPointValue];

secondPoint = [[pointArrayobjectAtIndex:1]CGPointValue];

thirdPoint = [[pointArrayobjectAtIndex:2]CGPointValue];
}

//关键方法,重新加载drawRect方法

[selfsetNeedsDisplay];
}

//绘制字符串
- (void)drawString:(id)sender
{

//设置字体颜色

UIColor *color = [UIColorcolorWithRed:1.0green:0.5blue:0alpha:1];

[colorset];

//要绘制的字符串

NSString *pstr =@"hello world!";

//设置字体

UIFont *font = [UIFontfontWithName:@"HelveticaNeue-Bold"size:18];

//从一个点开始绘制

[pstr drawAtPoint:CGPointMake(50,20)
withFont:font];

//设置区域
CGRect rect =
CGRectMake(100,70,
110, 120);

//在矩形区域内绘制
[pstrdrawInRect:rect
withFont:font];

}

//绘制图片
- (void)drawImage:(id)sender
{
UIImage *image = [UIImageimageNamed:@"4.png"];

//再指定坐标绘图

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

//在指定区域绘图
[imagedrawInRect:CGRectMake(0,100,
100, 100)];

//平铺绘图

[image drawAsPatternInRect:CGRectMake(220,350,
100,
100)];
}

//获取UIColor的各色组成部分
- (void)colorComents:(id)sender
{

//创建一个对象

UIColor *color = [UIColorcolorWithRed:0.5green:0.2blue:1alpha:1];

//获取CGColorRef
CGColorRef cgColor = [color
CGColor];

//通过颜色上下问获取一个CGFloat对象
const
CGFloat *colorComents =CGColorGetComponents(cgColor);

//获取颜色组成部分
NSUInteger componentCount =
CGColorGetNumberOfComponents(cgColor);

//循环输出颜色组成
for(int i =0;i < componentCount; i++)
{
NSLog(@"%.2f",colorComents[i]);
}
}

//绘制图形
- (void)drawMyGraph:(id)sender
{

//创建路径

CGMutablePathRef path =CGPathCreateMutable();

//创建区域
CGRect rect =
CGRectMake(10,310,
50, 140);

//将区域加到路径中
CGPathAddRect(path,
nil, rect);

//获取上下文

CGContextRef context =UIGraphicsGetCurrentContext();

//给矩形设置阴影

CGContextSetShadowWithColor(context,CGSizeMake(10,10),
20, [[UIColorblackColor]
CGColor]);

//将路径添加到上下文
CGContextAddPath(context, path);

//设置填充颜色

[[UIColorcolorWithRed:0.2green:1blue:0.5alpha:1.0
]setFill];

//设置边线颜色

[[UIColorredColor]
setStroke];

//设置线条宽度

CGContextSetLineWidth(context,5.0);

//在设置好的路径绘制

CGContextDrawPath(context,kCGPathEOFill);

//闭合路径

CGContextStrokePath(context);
}

//绘制线条
- (void)drawMyLine:(CGPoint)point
{

//设置线条颜色

[[UIColorblueColor]
set];

//获取上下文

CGContextRef context =UIGraphicsGetCurrentContext();

//设置起点

CGContextMoveToPoint(context,10,
20);

//设置中止点
CGContextAddLineToPoint(context, point.x ,point.y);

//连续画线条

CGContextAddLineToPoint(context,100,
50);

//设置线条宽度

CGContextSetLineWidth(context,10.0);

//线条连接处的样式

CGContextSetLineJoin(context,kCGLineJoinBevel);

//闭合路径

CGContextStrokePath(context);
}

//绘制圆形
- (void)drawRound:(id)sender
{

//获取上下文

CGContextRef context =UIGraphicsGetCurrentContext();

//根据上下问开始路径

CGContextBeginPath(context);

//设指绘制弧形的参数
CGContextAddArc(context,
260, 130,
40,0, 2*M_PI,1);

//设置绘制线条的颜色

CGContextSetRGBFillColor(context,1,
0,0,
1);

//闭合路径

CGContextFillPath(context);
}

- (void)dealloc
{
[_pointsrelease];

[superdealloc];
}

@end

运行结果:

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