iOS開發(fā)(高級特性)——Quartz2D

What is Quartz2D

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

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

When to use Quartz2D

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

Draw graphics

Provide graphics editing capabilities in an application

Create or display bitmap images

Work with PDF documents

對這上面這幾種翻譯一下:

1 )畫圖

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

2)提供圖形編輯功能

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

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

4)處理PDF文檔

How to use Quartz2D


concept

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

1)Painter's model


圖1

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

2)The Graphics Context

這個(gè)可以理解為繪畫環(huán)境,比如涂鴉繪畫環(huán)境就是墻壁,油畫的繪畫環(huán)境就是畫布。開發(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)大家還是比較熟悉的,過多的解釋沒有必要,值得注意的是在iOS的顯示中坐標(biāo)原點(diǎn)的位置不在左下角而在左上角。

5)Path

我們想要畫一個(gè)三角形或一個(gè)圓,在現(xiàn)實(shí)中我們可以根據(jù)抽象的思維,隨意畫出三角形和圓,但是計(jì)算機(jī)怎樣能夠準(zhǔn)確的畫出我們想要的圖案呢。Path就是用來定義圖形的??梢岳斫鉃镻ath表示了圖形的輪廓,按照這個(gè)輪廓,通過填充,描繪就可以準(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了我們就可以涂鴉啦,哦不對,是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說的就是這樣的一些變換??s放、移動(dòng),旋轉(zhuǎn)等。有坐標(biāo)系作為基礎(chǔ),這些變化對應(yīng)相應(yīng)的數(shù)學(xué)知識就很好理解了。簡單的直接調(diào)用API即可,復(fù)雜的變換可能要涉及到數(shù)學(xué)內(nèi)容,比如矩陣變換等,這些東西不在討論范圍。明白可能用到這些就好了


8)Partterns


9)Shadows

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

10)Gradient

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

理解了這些東西了,也很無聊的了,來個(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

簡單畫線


-(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)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,536評論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,505評論 2 379

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