概述
Core Graphics Framework是一套基于C的API框架,使用了Quartz作為繪圖引擎。它提供了低級別、輕量級、高保真度的2D渲染。該框架可以用于基于路徑的繪圖、變換、顏色管理、脫屏渲染,模板、漸變、遮蔽、圖像數(shù)據(jù)管理、圖像的創(chuàng)建、遮罩以及PDF文檔的創(chuàng)建、顯示和分析。Quartz 2D是Core Graphics Framework的一部分。能實現(xiàn)以下的功能
- 畫圖
- 在程序中提供圖形編輯
- 生成或者展示位圖
- 和PDF文檔工作
Painter Model
一個畫圖模型就是將CALayer上的內(nèi)容渲染到畫布上,
Graphics context
一個GraphicsContext對象是一個數(shù)據(jù)類型,封裝了Quartz圖像到設(shè)備的信息,總共有5種類型的context:
- 窗口
- 位圖
- 打印
- 反鋸齒
這些類型主要是包括:繪制參數(shù),設(shè)備相關(guān)信息。
圖形API
OpenGL ES是跨平臺的圖形API,屬于OpenGL的一個簡化版本。QuartZ 2D是蘋果公司開發(fā)的一套API.OpenGL ES是應(yīng)用程序編程接口,該接口描述了方法、結(jié)構(gòu)、函數(shù)應(yīng)具有的行為以及應(yīng)該如何被使用的語義。也就是說它只定義了一套規(guī)范,具體的實現(xiàn)由設(shè)備制造商根據(jù)規(guī)范去做.
Core Graphics API所有的操作都在一個上下文中進行
獲取當(dāng)前context的方法
調(diào)用UIGraphicsBeginImageContextWithOptions函數(shù)就可獲得用來處理圖片的圖形上下文。利用該上下文,你就可以在其上進行繪圖,并生成圖片。調(diào)用UIGraphicsGetImageFromCurrentImageContext函數(shù)可從當(dāng)前上下文中獲取一個UIImage對象。記住在你所有的繪圖操作后別忘了調(diào)用UIGraphicsEndImageContext函數(shù)關(guān)閉圖形上下文。UIView和CALayer中的渲染方法(比如drawRect和dispaly)中,默認(rèn)就是當(dāng)前的context上實現(xiàn)的,當(dāng)需要在其他的方法上去對layer上進行的渲染的時候,需要獲取當(dāng)前的山下文,通過func UIGraphicsGetCurrentContext() -> CGContext?獲取當(dāng)前的上下文。
繪圖形式
用Core Graphics之前需要指定一個用于繪圖的圖形上下文(CGContextRef),這個圖形上下文會在每個繪圖函數(shù)中都會被用到。用UIKit使用的時候自定義UIView,實現(xiàn)drawRect方法時,系統(tǒng)會自動的生成一個CGContextRef??偣灿?種的繪圖方式。
-
在UIView的子類方法drawRect:
func drawRect(_ aRect: NSRect) { var p = UIBezierPath(UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0,100,100)) UIColor.blueColor().setFill() p.fill() } -
使用Core Graphics,在
drawRect中實現(xiàn)func drawRect(_ aRect: NSRect) {
let con = UIGraphicsGetCurrentContext() CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100)) CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor) CGContextFillPath(con);}
CALayer的drawLayer上實現(xiàn) 。 view調(diào)用setNeedsDisplay,或者view.layer調(diào)用display。和1相似
和2相似,
CALayer的drawLayer上實現(xiàn) 通過提供的上下文-
UIGraphicsBeginImageContextWithOptions實現(xiàn)UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0); let p = UIBezierPath(bezierPathWithOvalInRect:CGRectMake(0,0,100,100)) UIColor.blueColor().setFill() p.fill() let im = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() -
使用
UIGraphicsBeginImageContextWithOptions基于Core Graphics實現(xiàn)UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0); let con = UIGraphicsGetCurrentContext(); CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100)); CGContextSetFillColorWithColor(con, UIColor.blueColor().CGColor); CGContextFillPath(con); let im = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
Quartz2D的數(shù)據(jù)類型
下面列出了Quartz 2D包含的數(shù)據(jù)類型:
CGPathRef:用于向量圖,可創(chuàng)建路徑,并進行填充或描畫(stroke)
CGImageRef:用于表示bitmap圖像和基于采樣數(shù)據(jù)的bitmap圖像遮罩。
CGLayerRef:用于表示可用于重復(fù)繪制(如背景)和幕后(offscreen)繪制的繪畫層
CGPatternRef:用于重繪圖
CGShadingRef、CGGradientRef:用于繪制漸變
CGFunctionRef:用于定義回調(diào)函數(shù),該函數(shù)包含一個隨機的浮點值參數(shù)。當(dāng)為陰影創(chuàng)建漸變時使用該類型
CGColorRef, CGColorSpaceRef:用于告訴Quartz如何解釋顏色
CGImageSourceRef,CGImageDestinationRef:用于在Quartz中移入移出數(shù)據(jù)
CGFontRef:用于繪制文本
CGPDFDictionaryRef, CGPDFObjectRef, CGPDFPageRef, CGPDFStream, CGPDFStringRef, CGPDFArrayRef:用于訪問PDF的元數(shù)據(jù)
CGPDFScannerRef, CGPDFContentStreamRef:用于解析PDF元數(shù)據(jù)
CGPSConverterRef:用于將PostScript轉(zhuǎn)化成PDF。在iOS中不能使用。
CGPath路徑的組成
- 線:實線,虛線--->通過
CGPathAddLines(_:_:_:_:)等方法 - 點:通過
moveToPoint(_:)等方法。 - ?。?code>CGContextAddArc(_:_:_:_:_:_:_:)和
CGContextAddArcToPoint(_:_:_:_:_:_:)等方法添加弧線 - 曲線:可以通過貝塞爾曲線獲取
CGContextAddArcToPoint(_:_:_:_:_:_:),或者自己定義一個貝塞爾曲線 - 最后可以選擇閉合曲線
CGContextClosePath(_:)
路徑的創(chuàng)建
具體步驟是:
- 通過
UIGraphicsGetCurrentContext獲取上下文,如果是在UIView和CALayer的渲染方法中,可以不用獲取 - 在開始繪制路徑前,調(diào)用函數(shù)
CGContextBeginPath,用CGContextBeginPath來標(biāo)記Quartz,因為context一個時間只能有一個path被使用,如果不使用的話,會丟棄之前的path - 進行線和點的繪制,
CGContextMoveToPoint CGContextAddLineToPoint - 通過
CGContextAddPath(_:_:)將路線加到上下文上
繪制路徑
路徑的繪制包括填充和描邊,在繪制前可以先設(shè)置繪制屬性,包括線寬,顏色等。
描邊
描邊的屬性包括:線寬,連接點,是否為虛線。以下是一些常用的描邊函數(shù)

填充
- 填充區(qū)域:填充當(dāng)前路徑時,Quartz將路徑包含的每個子路徑都看作是閉合的。然后,使用這些閉合路徑并計算填充的像素。但是如果路徑是由幾個重疊的部分組成或者路徑包含多個子路徑,則需一定的規(guī)則來定義填充區(qū)域(具體參考官方文檔)
- 填充模式:Quartz默認(rèn)使用普通混合模式(normal blend mode),也就是多種顏色重疊的時候,繪制模式。
路徑剪裁
繪制時,Quartz只渲染裁剪區(qū)內(nèi)的路徑,裁剪區(qū)域內(nèi)的閉合路徑是可見的;而在區(qū)域外的部分是不可見的。
顏色與顏色空間
顏色空間是指一個設(shè)備所能表示的顏色,通過以下方法
func deviceRGBColorSpace() -> NSColorSpace-
func deviceCMYKColorSpace() -> NSColorSpace
顏色空間有許多種,常用有RGB,CMY,HSB,CMYK,BGR等.alpha表示存在的對象與新對象如何混合。
CGContextSetAlpha可以指定全局alpha。
變化
在繪圖空間上,分為用戶空間和設(shè)備空間。context是作用在用戶空間的,然后通過CTM(current transformation matrix)映射到設(shè)備空間。CTM有三種操作包括平移CGContextTranslateCTM(_:_:_:),旋轉(zhuǎn)
CGContextRotateCTM(_:_:),縮放CGContextScaleCTM(_:_:_:)。從用戶空間到設(shè)備空間的映射空間可以通過
CGContextGetUserSpaceToDeviceSpaceTransform(_:)獲取到。
模式
模式(Pattern)是繪制操作的一個序列,這些繪制操作可以重復(fù)地繪制到一個圖形上下文上。當(dāng)用模式的時候,`Quartz將Page分割成模式單元格的集合,其中每個單元格的大小不是模式圖片的大小,并使用我們提供的回調(diào)函數(shù)來繪制這些單元格。模式單元格之間可以設(shè)置間距,并且在模式單元格上被繪制
陰影(Shadow)
陰影包括陰影偏移(iOS和MacOS的坐標(biāo)不一樣),通過CGContextSetShadow(_:_:_:)和CGContextSetShadowWithColor(_:_:_:_:)設(shè)置陰影。
具體的步驟如下:
- 保存圖形狀態(tài)
CGContextSaveGState(_:) - 調(diào)用
CGContextSetShadow(_:_:_:) - 使用陰影繪制對象
- 恢復(fù)圖形狀態(tài)
漸變
漸變對象主要是兩個CGShadingRef和CGGradientRef,CGGradientRef對象是對CGShadingRef的封裝,區(qū)別是不需要提供漸變計算函數(shù),只需要提供顏色和位置素組就好
CGGradientRef的創(chuàng)建和使用
使用過程:
- 創(chuàng)建
CGGradientRef對象,提供一個顏色空間,以及兩個以上的位置和顏色數(shù)組 - 調(diào)用
CGContextDrawLinearGradient(_:_:_:_:_:)或者CGContextDrawRadialGradient(_:_:_:_:_:_:_:) - 釋放內(nèi)存
使用CGGradient對象
一個CGGradient對象是一個漸變的抽象定義—它簡單地指定了顏色值和位置,但沒有指定幾何形狀。我們可以在軸向和徑向幾何形狀中使用這個對象。作為一個抽象定義,CGGradient對象可能比CGShading對象更容易重用。沒有將幾何形狀存儲在CGGradient對象中,這樣允許我們使用相同的顏色方案來繪制不同的幾何圖形,而不需要為多個圖形創(chuàng)建多個CGGradient對象。
因為Quartz為我們計算漸變,使用一個CGGradient對象來創(chuàng)建和繪制一個漸變則更直接,只需要以下幾步:
創(chuàng)建一個CGGradient對象,提供一個顏色空間,一個飽含兩個或更多顏色組件的數(shù)組,一個包含兩個或多個位置的數(shù)組,和兩個數(shù)組中元素的個數(shù)。
調(diào)用CGContextDrawLinearGradient或CGContextDrawRadialGradient函數(shù)并提供一個上下文、一個CGGradient對象、繪制選項和開始結(jié)束幾何圖形來繪制漸變。
當(dāng)不再需要時釋放CGGradient對象。
let locations = 2;
let locations[2] = { 0.0, 1.0 };
let components[8] = { 1.0, 0.5, 0.4, 1.0, 0.8, 0.8, 0.3, 1.0 }
let myColorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
let myGradient = CGGradientCreateWithColorComponents (myColorspace, components,locations, num_locations);
// myStartPoint, myEndPoint起始點和終點
CGContextDrawLinearGradient (myContext, myGradient, myStartPoint, myEndPoint, 0)
CGShadingRef的創(chuàng)建和使用
CGShadingRef分為創(chuàng)建和使用
CGShadingRef的創(chuàng)建
- 獲取顏色空間(
CGColorSpace) - 設(shè)置起始點和終點
- 起始半徑和終止半徑
-
CGFunctionCreate這個是關(guān)鍵:需要保證繪制到特低點的顏色值 - 一個bool值,指定是否用純色來繪制起始點和終點的擴展區(qū)(可選值)
CGShadingRef的使用
- 設(shè)置
CGFunction對象計算顏色值 : 也就是計算每一個位置的顏色 - 創(chuàng)建
CGShadingRef對象 - 裁剪上下文
- 使用
CGShading對象:CGFunctionEvaluate的重寫 - 釋放對象
透明
Quartz為每一個上下文維護一個透明層棧,繪制透明層的步驟如下
- 調(diào)用
CGContextBeginTransparencyLayer(_:_:)方法表明開始繪制透明 - 在透明層中繪制需要的組合對象
- 調(diào)用
CGContextEndTransparencyLayer(_:)后,透明才會被繪制上去
CGImageRef類型
CGImageRef是CGGraphics 的一種重要的數(shù)據(jù)類型,主要處理的是位圖與圖像的遮罩。創(chuàng)建一個位圖(CGImageRef)時,Quartz使用以下信息:
- 位圖數(shù)據(jù)源:可以是一個Quartz數(shù)據(jù)提供者或者是一個Quartz圖像源。
- 可選的解碼數(shù)組。(Decode Array)
- 插值設(shè)置:這是一個布爾值,指定Quartz在重置圖像大小時是否使用插值算法。
- 渲染意圖:指定如何映射位于圖形上下文中的目標(biāo)顏色空間中的顏色。該值在圖像遮罩中不需要。
- 圖像尺寸
- 像素格式,包括每個分量中的位數(shù),每個像素的位數(shù)和每行中的字節(jié)數(shù)。
如何創(chuàng)建
創(chuàng)建一個位圖對象主要有以下幾種方法:
- 依賴于圖像的數(shù)據(jù)源
- 常用
CGImageCreate來創(chuàng)建一個我吐 - 從PNG,JPEG創(chuàng)建一個
CGImage對象,主要通過:CGImageSourceCreateWithURL(_:_:),CGImageSourceCreateImageAtIndex(_:_:_:) - 從位圖上下文獲取
CGImage對象。調(diào)用CGBitmapContextCreateImage(_:) - 從一個已存在圖像中創(chuàng)建子圖像
CGImageCreateWithImageInRect(_:_:)
遮罩
一個位圖圖像遮罩定義了如何轉(zhuǎn)換顏色,而不是使用哪些顏色。函數(shù)CGImageCreateWithMask通過將圖像遮罩使用到一個圖像上的方式來創(chuàng)建一個圖像。
總結(jié)
首先CoreGraphics是Quartz的一部分,這部分大多數(shù)是C語言結(jié)構(gòu)的,Swift和OC的使用上沒有太大區(qū)別。而在獲取到了上下文后,關(guān)鍵的是如何去確定Path,貝塞爾曲線等等,這部分也可以通過專門的工具,在這推薦一個好的軟件PaintCode,能直接導(dǎo)出Swift代碼和OC代碼。具體可以參考用Sketch和PaintCode快速得到繪制代碼。let's Swift