What is Quartz2D
UIView及其子類的應(yīng)用目前比較熟悉了映挂,下面開始學(xué)習(xí)一下Quartz2D。我們從名字上來大致猜測一下這個東西是干嗎的期吓,2D好說應(yīng)該是說的2維和3D不同敲茄。那么Quartz又是個啥呢?Quartz的本意是石英石多柑,也有石英表的意思。在Java中有個叫Quartz的開源的作業(yè)調(diào)度框架楣责,估計是取其石英表的含義竣灌。但是在蘋果開發(fā)中,這個名字到底怎么解釋秆麸,還真猜不到初嘹。本來想望文知意的,結(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ī)讉€關(guān)鍵字:drawing engine, resolution, device-independent, API。
這幾個關(guān)鍵詞加起來就是說房铭,我們可以調(diào)用Quartz 2D的接口來繪圖驻龟。至于后面的簡單易用,功能強大這一類的描述育叁,看看就好迅脐,不必較真芍殖。
我們已經(jīng)知道了Quartz2D是什么豪嗽,也知道它能干什么,接下來就是學(xué)習(xí)它是怎么做的豌骏。
When to use Quartz2D
討論怎么用之前龟梦,我們先了解一下什么時候用,即應(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ù)雜一點,如照片處理一類的衰抑。
3)創(chuàng)建或者顯示位圖
4)處理PDF文檔
How to use Quartz2D
concept
我們先理解一些概念象迎,不然理解后面說的東西比較費勁。
1)Painter's model
看圖1來理解這個所謂的粉刷模型,就是一個粉刷效果砾淌,后面的掩蓋前面的啦撮。
2)The Graphics Context
這個可以理解為繪畫環(huán)境,比如涂鴉繪畫環(huán)境就是墻壁汪厨,油畫的繪畫環(huán)境就是畫布赃春。開發(fā)中的繪畫環(huán)境有:位圖,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
UIGraphicsBeginImageContextWithOptions//iOS環(huán)境中用這個脱惰,避免坐標(biāo)系統(tǒng)的不同
3)Opaque Data Types
數(shù)據(jù)類型很多搏嗡,我們用到的時候在詳細(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)原點的位置不在左下角而在左上角磅氨。
5)Path
我們想要畫一個三角形或一個圓,在現(xiàn)實中我們可以根據(jù)抽象的思維嫡纠,隨意畫出三角形和圓烦租,但是計算機怎樣能夠準(zhǔn)確的畫出我們想要的圖案呢。Path就是用來定義圖形的除盏〔娉鳎可以理解為Path表示了圖形的輪廓,按照這個輪廓者蠕,通過填充窃祝,描繪就可以準(zhǔn)確的得到我們想要的圖案。
直接在Context上畫
創(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說的就是這樣的一些變換玉转⊥幌耄縮放、移動,旋轉(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
有時候一種顏色,或者簡單疊加的顏色看起來很枯燥乏味擅腰,我們用漸變讓圖形更豐富蟋恬。
理解了這些東西了,也很無聊的了趁冈,來個例子吧歼争,看看這些東西到底是怎么玩的。
@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ū)域的覆蓋)
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)容不用記得太清楚,用的時候有個印象能快速查詢到相關(guān)文檔既可以了旺坠。