Quartz 2D是二維圖形繪製引擎,可以實現N多圖形圖像的操作功能,如基本路徑的繪製、透明度、描影、繪製陰影、透明層、顏色管理、反鋸齒、PDF文檔生成和PDF元數據訪問。
畫布Page
在圖像操作過程中使用了繪畫者模型
,繪製過程是將繪製層鋪到畫布上,這個畫布稱爲Page
。類似於Photoshop中,將每個圖層疊加放在畫布上,形成最後的圖像。
圖形上下文Graphics Context
圖形上下文(Graphics Context)
是一個數據類型CGContextRef
,它存放了Quartz 2D繪製的圖形輸出信息,可以看做是圖形到設備輸出的介質工具。Quartz 2D繪製的圖形可以放到多種設備上,比如:PDF文件、顯示器窗口、bitmap(位圖)、view的Layer層等等,這就需要不同的Graphics Context
來完成輸出到不同設備上的工作。這好比人要上高速需要汽車,去海上需要船,去天空需要飛機,這裏人相當於圖形,高速路、海、天空相當於設備,而汽車、船、飛機就是Graphics Context
。
Graphics Context
的幾種類型
|
|
Quartz 2D的數據類型
Quartz 2D API屬於Code Graphics框架,所以Quartz 2D的數據類型是以CG開頭的。有以下數據類型:
|
|
圖形狀態
Quartz通過修改圖形狀態來修改繪製結果,圖形狀態直接決定了圖形的最終渲染結果。圖形狀態包含用於繪製程序的參數,繪製參數改變了,圖形自然就變了。比如修改了填充色值,圖形顏色就變了。
iOS中使用Graphics Context繪製圖形
在iOS中要想用Quartz 2D在屏幕上繪圖,需要自定義一個UIView,在UIView的- (void)drawRect:(CGRect)rect
方法中實現繪圖操作,這個方法會在UIView顯示在屏幕上和需要被刷新的時候調用。創建上下文的方法如下:
|
|
在上下文中繪製圖形:
|
|
注意:設置填充色和填充矩形的方法順序不能顛倒,不然填充色填充不到想填充的矩形中。得不到填充色填充的會是黑色。
路徑
路徑可以構建出多種圖形,可以是點、直線、弧線、不規則線、規則或不規則形狀,可以對閉合路徑進行填充行程面。使用路徑繪製出想要的圖形,有兩步:創建路徑和繪製路徑。創建出點、線等路徑,使用函數CGContextDrawPath
繪製路徑。
點
點是依靠x、y值固定的位置,可作爲路徑的起始點位置。比如要畫一個線段,必須要有一個起點和一個終點,兩點確定一條線段。使用函數CGContextMoveToPoint
來確定起始點,傳入圖形上下文和x,y座標點。
|
|
直線
有起始點,再指定一個終點位置就能確定一條直線了,使用函數CGContextAddLineToPoint
來指定終點位置。
|
|
可以使用CGContextAddLineToPoint
函數指定多個位置點,線段會一個接一個畫下去,形成折線圖形。也可以使用CGContextAddLines
函數一次性指定多個位置點,完成折線圖形,此時無需指定起始點,第一個點默認爲起始點(即使用CGContextMoveToPoint
指定起始點也無效)。
|
|
由於CGContextAddLineToPoint
函數必須得有CGContextMoveToPoint
函數固定起始點,CGContextAddLines
函數默認第一個點爲起始點,所以CGContextAddLines
後面可以跟着CGContextAddLineToPoint
繼續加點畫線,能連成一組折線,而CGContextMoveToPoint
+CGContextAddLineToPoint
畫線後面不能跟CGContextAddLines
,會畫成兩組無關聯的折線。
圓弧
畫圓弧提供了兩個函數,一個是CGContextAddArc
,依次指定圖形上下文
、圓心座標
、半徑
、起始弧度
、終止弧度
、畫線順時針(1)或逆時針(0)
。
|
|
第二個函數是CGContextAddArcToPoint
,三點+半徑確定一個圓弧。CGContextMoveToPoint
函數確定第一個點,CGContextAddArcToPoint
添加第二個點、第三個點和還有半徑。原理:以第二點爲中心,分別向第一點、第三點延長兩條射線,射線夾角小於180°的一側,以指定半徑畫圓弧,圓弧與射線相切。
|
|
曲線
畫Bezier曲線也提供了兩個函數,函數CGContextAddCurveToPoint
用於畫三次Bezier曲線,由一個起點、一個終點和兩個控制點構成一條三次Bezier曲線。當兩個控制點在起點和終點連線的同側時,曲線會只有一個拱向,在不同側時有兩個拱向。
|
|
畫二次Bezier曲線,使用函數CGContextAddQuadCurveToPoint。以當前點爲起始點,指定一個控制點一個終點,確定一條二次Bezier曲線。控制點決定了曲線拱的方向,該函數只能創建一個拱向的Bezier曲線,而且曲線不可能交叉。
|
|
閉合路徑
Quartz 2D提供函數CGContextClosePath
來閉合路徑。就是將終點和起點用直線連接起來,使整個路徑閉合。對於直線、弧、曲線等不能自動閉合的路徑,如果想完成路徑閉合必須調用該函數。
調用了CGContextClosePath
完成閉合路徑後,再調用Add...
添加路徑的函數,添加直線、弧線、曲線等路徑,會從閉合路徑的起始點開始。如果沒有完成閉合路徑函數的調用,則從終點繼續開始新添加的路徑。
|
|
矩形
使用函數CGContextAddRect
來畫矩形,函數中的rect
中x,y是矩形左上角,寬高是矩形的寬高。
|
|
橢圓
使用函數CGContextAddEllipseInRect
來畫橢圓,是以矩形來確定橢圓。座標參數意義和矩形一樣,以確定的矩形內切畫出的橢圓。矩形的圓心即是橢圓的圓心,矩形的寬高即是橢圓的長軸短軸,當矩形的寬高相等時,橢圓就是一個圓了。
|
|
創建路徑
- 在開始繪製路徑前,調用 CGContextBeginPath 或 UI。
- 直線、弧、曲線開始於當前點。空路徑沒有當前點;我們必須調用CGContextMoveToPoint來設置第一個子路徑的起始點,或者調用一個便利函數來隱式地完成該任務。
- 如果要閉合當前子路徑,調用函數 CGContextClosePath。隨後路徑將開始一個新的子路徑,即使我們不顯示設置一個新的起始點。
- 當繪製弧時,Quartz 將在當前點與弧的起始點間繪製一條直線。
- 添加橢圓和矩形的 Quartz 程序將在路徑中添加新的閉合子路徑。
- 我們必須調用繪製函數來填充或者描邊一條路徑,因爲創建路徑時並不會繪製路徑。
- Quartz 提供了兩個數據類型來創建可複用路徑 CGPathRef 和 CGMutablePathRef。
- Quartz 提供了一個類似於操作圖形上下文的 CGPath 的函數集合。這些路徑函數操作 CGPath 對象,而不是圖形上下文。
|
|
如果想要添加一個路徑到圖形上下文,可以調用CGContextAddPath。路徑將保留在圖形上下文中,直到Quartz繪製它。我們可以調用CGContextAddPath再次添加路徑。
繪製路徑
通過圖形上下文加上一系列創建路徑的函數得到最終的路徑,還需要繪製路徑操作,才能使得路徑呈現。如上文中一直用到的繪製路徑的函數操作CGContextDrawPath(context, kCGPathStroke);
。
繪製路徑分爲描邊和填充,描邊是繪製路徑的邊框,填充是繪製路徑所包含的區域。
影響描邊的屬性
函數 | 解釋 | 備註 |
---|---|---|
CGContextSetLineWidth | 描邊路徑的寬度 | 單位是用戶空間單位 |
CGContextSetLineJoin | 指定描邊的連接點樣式 | 枚舉類型:Miter(尖角),Round(圓角),Bevel(平角) |
CGContextSetLineCap | 指定直線端點樣式 | 枚舉類:Butt,Round,Square |
CGContextSetMiterLimit | 轉角的量級 | |
CGContextSetLineDash | 虛線模式 | 指定虛線數組和虛線相位控制虛線大小和位置 |
CGContextSetStrokeColorSpace | 描邊顏色空間 | 封裝了顏色和顏色空間的CGColorRef |
CGContextSetStrokeColor | 設置描邊顏色 | |
CGContextSetStrokePattern | 筆觸模式 |
填充路徑
填充規則有兩種:非零纏繞數規則(nonzero winding number rule)、偶數-奇數規則(even-odd rule)。
默認的填充規則爲非零纏繞數規則。方法或枚舉帶有“EO”的爲偶數-奇數規則。
非零纏繞數的填充規則與繪製的方向有關、偶數-奇數規則則與方向無關。如圖。
函數 | 解釋 |
---|---|
CGContextEOFillPath | 使用偶數奇數規則填充當前路徑 |
CGContextFillPath | 使用非零纏繞數規則填充當前路徑 |
CGContextFillRect | 快速填充一個矩形 |
CGContextFillRects | 快速填充N個矩形 |
CGContextFillEllipseInRect | 快速填充一個橢圓形 |
CGContextDrawPath | 填充或描邊路徑 |
CGContextDrawPath函數的使用:
- CGContextDrawPath(context, kCGPathFill) 填充路徑。
- CGContextDrawPath(context, kCGPathEOFill) 使用奇偶規則填充路徑。
- CGContextDrawPath(context, kCGPathStroke) 描邊路徑。
- CGContextDrawPath(context, kCGPathFillStroke) 填充並描邊路徑。
- CGContextDrawPath(context, kCGPathEOFillStroke) 使用奇偶規則填充並描邊路徑。
混合模式
混合模式是Quartz將繪圖繪製到背景上的方式,其實就是前景圖和背景圖怎麼混合疊加。疊加公式如下:
|
|
Quartz默認使用普通混合模式,也就是kCGBlendModeNormal
。下面舉例幾個混合模式的樣式,案例樣式的代碼見下一節裁剪路徑
:
kCGBlendModeNormal | kCGBlendModeMultiply | kCGBlendModeScreen |
---|---|---|
16種混合模式:
|
|
裁剪路徑
裁剪是一個遮罩,會遮住不允許繪製的地方。裁剪區域是一個閉合路徑,Quartz只會渲染裁剪區域裏面的東西,外面的東西不渲染。通過函數CGContextClip
裁剪,具體的裁剪代碼和執行結果如下,注意代碼位置:
|
|
執行結果:
參考文章:南峯子翻譯的Quartz2D編程指南