iOS開(kāi)發(fā)(高級(jí)特性)——Quartz2D

What is Quartz2D

UIView及其子類的應(yīng)用目前比較熟悉了,下面開(kāi)始學(xué)習(xí)一下Quartz2D。我們從名字上來(lái)大致猜測(cè)一下這個(gè)東西是干嗎的,2D好說(shuō)應(yīng)該是說(shuō)的2維和3D不同。那么Quartz又是個(gè)啥呢?Quartz的本意是石英石,也有石英表的意思。在Java中有個(gè)叫Quartz的開(kāi)源的作業(yè)調(diào)度框架,估計(jì)是取其石英表的含義。但是在蘋果開(kāi)發(fā)中,這個(gè)名字到底怎么解釋,還真猜不到。本來(lái)想望文知意的,結(jié)果不太靠譜,那我們直接先看一看蘋果對(duì)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

這么一大段話,我們找?guī)讉€(gè)關(guān)鍵字:drawing engine, resolution, device-independent, API。

這幾個(gè)關(guān)鍵詞加起來(lái)就是說(shuō),我們可以調(diào)用Quartz 2D的接口來(lái)繪圖。至于后面的簡(jiǎn)單易用,功能強(qiáng)大這一類的描述,看看就好,不必較真。

我們已經(jīng)知道了Quartz2D是什么,也知道它能干什么,接下來(lái)就是學(xué)習(xí)它是怎么做的。

When to use Quartz2D

討論怎么用之前,我們先了解一下什么時(shí)候用,即應(yīng)用場(chǎng)景。還是看蘋果給的東西吧,畢竟這玩意都是他們搞出來(lái)的。

Draw graphics

Provide graphics editing capabilities in an application

Create or display bitmap images

Work with PDF documents

對(duì)這上面這幾種翻譯一下:

1 )畫圖

這里說(shuō)的畫圖,應(yīng)該是指在界面上畫線條,多邊形,弧形等。如股票軟件中的各種線條。

2)提供圖形編輯功能

圖片編輯功能復(fù)雜一點(diǎn),如照片處理一類的。

3)創(chuàng)建或者顯示位圖

4)處理PDF文檔

How to use Quartz2D


concept

我們先理解一些概念,不然理解后面說(shuō)的東西比較費(fèi)勁。

1)Painter's model


圖1

看圖1來(lái)理解這個(gè)所謂的粉刷模型,就是一個(gè)粉刷效果,后面的掩蓋前面的。

2)The Graphics Context

這個(gè)可以理解為繪畫環(huán)境,比如涂鴉繪畫環(huán)境就是墻壁,油畫的繪畫環(huán)境就是畫布。開(kāi)發(fā)中的繪畫環(huán)境有:位圖,PDF,窗口,圖層。

Creating a Window Graphics Context,API本身不能獲取window的Context,需要在Cocoa framework中獲取一個(gè)。

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

Creating a PDF Graphics Context

CGPDFContextCreateWithURL

CGPDFContextCreate

Creating a Bitmap Graphics Context

CGBitmapContextCreate

UIGraphicsBeginImageContextWithOptions//iOS環(huán)境中用這個(gè),避免坐標(biāo)系統(tǒng)的不同

3)Opaque Data Types

數(shù)據(jù)類型很多,我們用到的時(shí)候在詳細(xì)了解。下面列一下這些數(shù)據(jù)類型和用處:

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

CGImageRef, used to represent bitmap images and bitmap image masks based on sample data that you supply. SeeBitmap 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. SeeCore Graphics Layer Drawing

CGPatternRef, used for repeated drawing. SeePatterns.

CGShadingRefandCGGradientRef, used to paint gradients. SeeGradients.

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. SeeGradients.

CGColorRefandCGColorSpaceRef, used to inform Quartz how to interpret color. SeeColor and Color Spaces.

CGImageSourceRefandCGImageDestinationRef, which you use to move data into and out of Quartz. SeeData Management in Quartz 2DandImage I/O Programming Guide.

CGFontRef, used to draw text. SeeText.

CGPDFDictionaryRef,CGPDFObjectRef,CGPDFPageRef,CGPDFStream,CGPDFStringRef,andCGPDFArrayRef, which provide access to PDF metadata. SeePDF Document Creation, Viewing, and Transforming.

CGPDFScannerRefandCGPDFContentStreamRef, which parse PDF metadata. SeePDF Document Parsing.

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

4)Coordinate Systems

在二維中繪圖,坐標(biāo)系的概念必不可少。指標(biāo)系統(tǒng)大家還是比較熟悉的,過(guò)多的解釋沒(méi)有必要,值得注意的是在iOS的顯示中坐標(biāo)原點(diǎn)的位置不在左下角而在左上角。

5)Path

我們想要畫一個(gè)三角形或一個(gè)圓,在現(xiàn)實(shí)中我們可以根據(jù)抽象的思維,隨意畫出三角形和圓,但是計(jì)算機(jī)怎樣能夠準(zhǔn)確的畫出我們想要的圖案呢。Path就是用來(lái)定義圖形的。可以理解為Path表示了圖形的輪廓,按照這個(gè)輪廓,通過(guò)填充,描繪就可以準(zhǔn)確的得到我們想要的圖案。

直接在Context上畫

CGContextMoveToPoint

CGContextAddLineToPoint

CGContextAddLines

CGContextAddArc

CGContextAddArcToPoint

CGContextAddCurveToPoint

CGContextAddQuadCurveToPoint

CGContextClosePath

CGContextAddEllipseInRect

CGContextAddRect

創(chuàng)建可復(fù)用的Path

CGPathCreateMutable, which replacesCGContextBeginPath

CGPathMoveToPoint, which replacesCGContextMoveToPoint

CGPathAddLineToPoint, which replacesCGContextAddLineToPoint

CGPathAddCurveToPoint, which replacesCGContextAddCurveToPoint

CGPathAddEllipseInRect, which replacesCGContextAddEllipseInRect

CGPathAddArc, which replacesCGContextAddArc

CGPathAddRect, which replacesCGContextAddRect

CGPathCloseSubpath, which replacesCGContextClosePath

將Path加到Context上CGContextAddPath.

有了Path了我們就可以涂鴉啦,哦不對(duì),是Paint.有兩種方式,填充(filling)和筆畫(stroking)。

Parameters That Affect Stroking

Parameter:Function to set parameter value

Line width:CGContextSetLineWidth//線寬度

Line join:CGContextSetLineJoin//連接處的風(fēng)格設(shè)置

Line cap:CGContextSetLineCap//兩端的風(fēng)格

Miter limit:CGContextSetMiterLimit //

Line dash pattern:CGContextSetLineDash

Stroke color space:CGContextSetStrokeColorSpace

Stroke color:CGContextSetStrokeColorCGContextSetStrokeColorWithColor

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

顏色的相關(guān)內(nèi)容。

7) Transform

如圖,Transform說(shuō)的就是這樣的一些變換。縮放、移動(dòng),旋轉(zhuǎn)等。有坐標(biāo)系作為基礎(chǔ),這些變化對(duì)應(yīng)相應(yīng)的數(shù)學(xué)知識(shí)就很好理解了。簡(jiǎn)單的直接調(diào)用API即可,復(fù)雜的變換可能要涉及到數(shù)學(xué)內(nèi)容,比如矩陣變換等,這些東西不在討論范圍。明白可能用到這些就好了


8)Partterns


9)Shadows

陰影可以讓2D的圖形有3D的視覺(jué)效果。

10)Gradient

有時(shí)候一種顏色,或者簡(jiǎn)單疊加的顏色看起來(lái)很枯燥乏味,我們用漸變讓圖形更豐富。

理解了這些東西了,也很無(wú)聊的了,來(lái)個(gè)例子吧,看看這些東西到底是怎么玩的。

@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.準(zhǔn)備繪圖

3.設(shè)置填充顏色(涉及到Color相關(guān)內(nèi)容)

4.填充矩形區(qū)域(涉及到path相關(guān)內(nèi)容)

5.再次設(shè)置顏色(透明相關(guān))

6.填充矩形區(qū)域(根據(jù)Painter's Model 覆蓋,重疊區(qū)域的覆蓋)

圖2


Demo

1)QuartzLines

簡(jiǎn)單畫線


-(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的內(nèi)容就不一一貼代碼和貼圖了。這些內(nèi)容不用記得太清楚,用的時(shí)候有個(gè)印象能快速查詢到相關(guān)文檔既可以了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容