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

iOS开发——Quartz2D

2016-09-12 04:54 344 查看
转载自:http://www.jianshu.com/p/0e5fe91d0196

What is Quartz2D

UIView及其子类的应用目前比较熟悉了,下面开始学习一下Quartz2D。我们从名字上来大致猜测一下这个东西是干吗的,2D好说应该是说的2维和3D不同。那么Quartz又是个啥呢?Quartz的本意是石英石,也有石英表的意思。在Java中有个叫Quartz的开源的作业调度框架,估计是取其石英表的含义。但是在苹果开发中,这个名字到底怎么解释,还真猜不到。本来想望文知意的,结果不太靠谱,那我们直接先看一看苹果对Quartz 2D的描述

Quartz 2D is an advanced, two-dimensional drawing engine available for iOS application development and to all Mac OS X application environments outside of the kernel. Quartz 2D provides low-level, lightweight 2D rendering with unmatched output fidelity regardless
of display or printing device. Quartz 2D is resolution- and device-independent; you don’t need to think about the final destination when you use the Quartz 2D application programming interface (API) for drawing.

The Quartz 2D API is easy to use and provides access to powerful features such as transparency layers, path-based drawing, offscreen rendering, advanced color management, anti-aliased rendering, and PDF document creation, display, and parsing.

The Quartz 2D API is part of the Core Graphics framework, so you may see Quartz referred to as Core Graphics or, simply, CG

这么一大段话,我们找几个关键字:drawing engine, resolution, device-independent, API。

这几个关键词加起来就是说,我们可以调用Quartz 2D的接口来绘图。至于后面的简单易用,功能强大这一类的描述,看看就好,不必较真。

我们已经知道了Quartz2D是什么,也知道它能干什么,接下来就是学习它是怎么做的。

When to use Quartz2D

讨论怎么用之前,我们先了解一下什么时候用,即应用场景。还是看苹果给的东西吧,毕竟这玩意都是他们搞出来的。

Draw graphics

Provide graphics editing capabilities in an application

Create or display bitmap images

Work with PDF documents

对这上面这几种翻译一下:

1 )画图

这里说的画图,应该是指在界面上画线条,多边形,弧形等。如股票软件中的各种线条。

2)提供图形编辑功能

图片编辑功能复杂一点,如照片处理一类的。

3)创建或者显示位图

4)处理PDF文档

How to use Quartz2D

concept

我们先理解一些概念,不然理解后面说的东西比较费劲。

1)Painter's model


图1

看图1来理解这个所谓的粉刷模型,就是一个粉刷效果,后面的掩盖前面的。

2)The Graphics Context

这个可以理解为绘画环境,比如涂鸦绘画环境就是墙壁,油画的绘画环境就是画布。开发中的绘画环境有:位图,PDF,窗口,图层。

Creating a Window Graphics Context,API本身不能获取window的Context,需要在Cocoa framework中获取一个。

CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];//

Creating a PDF Graphics Context

CGPDFContextCreateWithURL

CGPDFContextCreate

Creating a Bitmap Graphics Context

CGBitmapContextCreate

UIGraphicsBeginImageContextWithOptions
//iOS环境中用这个,避免坐标系统的不同

3)Opaque Data Types

数据类型很多,我们用到的时候在详细了解。下面列一下这些数据类型和用处:

CGPathRef , used for vector graphics to create paths that
you fill or stroke. See
Paths .

CGImageRef , used to represent bitmap images and bitmap
image masks based on sample data that you supply. See
Bitmap Images and Image Masks .

CGLayerRef , used to represent a drawing layer that can
be used for repeated drawing (such as for backgrounds or patterns) and for offscreen drawing. See

Core Graphics Layer Drawing

CGPatternRef , used for repeated drawing. See

Patterns .

CGShadingRef and

CGGradientRef , used to paint gradients. See
Gradients .

CGFunctionRef , used to define callback functions
that take an arbitrary number of floating-point arguments. You use this data type when you create gradients for a shading. See

Gradients .

CGColorRef and

CGColorSpaceRef , used to inform Quartz how to interpret color. See
Color and Color Spaces .

CGImageSourceRef and

CGImageDestinationRef , which you use to move data into and out of Quartz. See

Data Management in Quartz 2D and Image
I/O Programming Guide .

CGFontRef , used to draw text. See

Text .

CGPDFDictionaryRef ,

CGPDFObjectRef ,
CGPDFPageRef ,
CGPDFStream ,
CGPDFStringRef ,and
CGPDFArrayRef , which provide access to PDF metadata. See
PDF Document Creation, Viewing, and Transforming .

CGPDFScannerRef and

CGPDFContentStreamRef , which parse PDF metadata. See
PDF Document Parsing .

CGPSConverterRef , used to convert PostScript
to PDF. It is not available in iOS. See
PostScript Conversion .

4)Coordinate Systems

在二维中绘图,坐标系的概念必不可少。指标系统大家还是比较熟悉的,过多的解释没有必要,值得注意的是在iOS的显示中坐标原点的位置不在左下角而在左上角。

5)Path

我们想要画一个三角形或一个圆,在现实中我们可以根据抽象的思维,随意画出三角形和圆,但是计算机怎样能够准确的画出我们想要的图案呢。Path就是用来定义图形的。可以理解为Path表示了图形的轮廓,按照这个轮廓,通过填充,描绘就可以准确的得到我们想要的图案。

直接在Context上画

CGContextMoveToPoint

CGContextAddLineToPoint

CGContextAddLines

CGContextAddArc

CGContextAddArcToPoint

CGContextAddCurveToPoint

CGContextAddQuadCurveToPoint

CGContextAddEllipseInRect

CGContextAddRect

创建可复用的Path

CGPathCreateMutable , which replaces

CGContextBeginPath

CGPathMoveToPoint , which replaces

CGContextMoveToPoint

CGPathAddLineToPoint , which replaces

CGContextAddLineToPoint

CGPathAddCurveToPoint , which replaces

CGContextAddCurveToPoint

CGPathAddEllipseInRect , which replaces

CGContextAddEllipseInRect

CGPathAddArc , which replaces

CGContextAddArc

CGPathAddRect , which replaces

CGContextAddRect

CGPathCloseSubpath , which replaces

CGContextClosePath

将Path加到Context上
CGContextAddPath .

有了Path了我们就可以涂鸦啦,哦不对,是Paint.有两种方式,填充(filling)和笔画(stroking)。

Parameters That Affect Stroking

Parameter:Function to set parameter value

Line width:
CGContextSetLineWidth //线宽度

Line join:
CGContextSetLineJoin //连接处的风格设置

Line cap:
CGContextSetLineCap //两端的风格

Miter limit:
CGContextSetMiterLimit //

Line dash pattern:
CGContextSetLineDash

Stroke color space:
CGContextSetStrokeColorSpace

Stroke color:
CGContextSetStrokeColor
CGContextSetStrokeColorWithColor

Stroke pattern:
CGContextSetStrokePattern

Functions that fill paths

CGContextEOFillPath

Fills the current path using the even-odd rule.

CGContextFillPath

Fills the current path using the nonzero winding number rule.

CGContextFillRect

Fills the area that fits inside the specified rectangle.

CGContextFillRects

Fills the areas that fits inside the specified rectangles.

CGContextFillEllipseInRect

Fills an ellipse that fits inside the specified rectangle.

CGContextDrawPath

Fills the current path if you pass kCGPathFill(nonzero winding number rule) or kCGPathEOFill(even-odd rule). Fills and strokes the current path if you pass kCGPathFillStroke or kCGPathEOFillStroke.

6)Color and Color Space

7) Transform

8)Partterns

9)Shadows

10)Gradient

理解了这些东西了,也很无聊的了,来个例子吧,看看这些东西到底是怎么玩的。

@implementation MyQuartzView

- (id)initWithFrame:(NSRect)frameRect

{

self = [super initWithFrame:frameRect];

return self;

}

- (void)drawRect:(NSRect)rect

{

CGContextRef myContext = [[NSGraphicsContext

currentContext] graphicsPort]; // 1

// ********** Your drawing code here **********// 2

CGContextSetRGBFillColor (myContext, 1, 0, 0, 1);// 3

CGContextFillRect (myContext, CGRectMake (0, 0, 200, 100 ));// 4

CGContextSetRGBFillColor (myContext, 0, 0, 1, .5);// 5

CGContextFillRect (myContext, CGRectMake (0, 0, 100, 200));// 6

}

@end

得到的效果如图2

1.获取Context

2.准备绘图

3.设置填充颜色(涉及到Color相关内容)

4.填充矩形区域(涉及到path相关内容)

5.再次设置颜色(透明相关)

6.填充矩形区域(根据Painter's Model 覆盖,重叠区域的覆盖)


图2

Demo

1)QuartzLines

简单画线

-(void)drawInContext:(CGContextRef)context

{

// Drawing lines with a white stroke color

CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

// Draw them with a 2.0 stroke width so they are a bit more visible.

CGContextSetLineWidth(context, 2.0);

// Draw a single line from left to right

CGContextMoveToPoint(context, 10.0, 30.0);

CGContextAddLineToPoint(context, 310.0, 30.0);

CGContextStrokePath(context);

// Draw a connected sequence of line segments

CGPoint addLines[] =

{

CGPointMake(10.0, 90.0),

CGPointMake(70.0, 60.0),

CGPointMake(130.0, 90.0),

CGPointMake(190.0, 60.0),

CGPointMake(250.0, 90.0),

CGPointMake(310.0, 60.0),

};

// Bulk call to add lines to the current path.

// Equivalent to MoveToPoint(points[0]); for(i=1; i < count,++i) AddLineToPoint(points[i]);

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

CGContextStrokePath(context);

CGPoint strokeSegments[] =

{

CGPointMake(10.0, 150.0),

CGPointMake(70.0, 120.0),

CGPointMake(130.0, 150.0),

CGPointMake(190.0, 120.0),

CGPointMake(250.0, 150.0),

CGPointMake(310.0, 120.0),

};

// Bulk call to stroke a sequence of line segments.

CGContextStrokeLineSegments(context, strokeSegments, sizeof(strokeSegments)/sizeof(strokeSegments[0]));



cap and join

-(void)drawInContext:(CGContextRef)context

{

// Drawing lines with a white stroke color

CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);

// Preserve the current drawing state

CGContextSaveGState(context);

// Setup the horizontal line to demostrate caps

CGContextMoveToPoint(context, 40.0, 30.0);

CGContextAddLineToPoint(context, 280.0, 30.0);

// Set the line width & cap for the cap demo

CGContextSetLineWidth(context, self.width);

CGContextSetLineCap(context, self.cap);

CGContextStrokePath(context);

// Restore the previous drawing state, and save it again.

CGContextRestoreGState(context);

CGContextSaveGState(context);

// Setup the angled line to demonstrate joins

CGContextMoveToPoint(context, 40.0, 190.0);

CGContextAddLineToPoint(context, 160.0, 70.0);

CGContextAddLineToPoint(context, 280.0, 190.0);

// Set the line width & join for the join demo

CGContextSetLineWidth(context, self.width);

CGContextSetLineJoin(context, self.join);

CGContextStrokePath(context);

// Restore the previous drawing state.

CGContextRestoreGState(context);

// If the stroke width is large enough, display the path that generated these lines

if (self.width >= 4.0) // arbitrarily only show when the line is at least twice as wide as our target stroke

{

CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);

CGContextMoveToPoint(context, 40.0, 30.0);

CGContextAddLineToPoint(context, 280.0, 30.0);

CGContextMoveToPoint(context, 40.0, 190.0);

CGContextAddLineToPoint(context, 160.0, 70.0);

CGContextAddLineToPoint(context, 280.0, 190.0);

CGContextSetLineWidth(context, 2.0);

CGContextStrokePath(context);

}

}

-(void)setCap:(CGLineCap)c

{

if(c != _cap)

{

_cap = c;

[self setNeedsDisplay];

}

}

-(void)setJoin:(CGLineJoin)j

{

if(j != _join)

{

_join = j;

[self setNeedsDisplay];

}

}

-(void)setWidth:(CGFloat)w

{

if(w != _width)

{

_width = w;

[self setNeedsDisplay];

}

}





2)QuartzPoly

3)QuartzGradient

4)QuartzDash

5)QuartzPolygons

6)QuartzCurves

7)QuartzImages

8)QuartzRendering

9) QuartzClipping

2到9的内容就不一一贴代码和贴图了。这些内容不用记得太清楚,用的时候有个印象能快速查询到相关文档既可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Quartz2D