Quartz 2D
是一個二維繪圖引擎,同時支持iOS和Mac系統。 其實 iOS 中不少控件都是經過 Quartz 2D
畫出來的. 同時Quartz 2D
還能夠作這些事情,swift
一、剪裁圖形
二、塗鴉/畫板(如簽名等)
三、手勢解鎖(連線)
四、折線圖、餅狀圖、柱形圖等繪製(雖然我都是直接用 charts)
複製代碼
使用 Quartz 2D
繪圖的核心步驟:bash
一、得到上下文
二、繪製/拼接繪圖路徑
三、將路徑添加到上下文
四、渲染上下文
記住:全部的繪圖,都是這個步驟,即便使用貝塞爾路徑,也只是對這個步驟進行了封裝。
對於繪圖而言,拿到上下文很關鍵。
複製代碼
其中圖形上下文有五種 函數
Bitmap Graphics Context
PDF Graphics Context
Window Graphics Context
Layer Graphics Context
Printer Graphics Context
複製代碼
使用Quartz 2D
自定義 UI 控件繪圖的方法動畫
1.新建一個類,繼承自UIView
2.必須實現- (void)drawRect:(CGRect)rect方法,而後在這個方法中,能夠:
取得跟當前view相關聯的圖形上下文
繪製相應的圖形內容,繪製時產生的線條稱爲路徑。 路徑由一個或多個直線段或曲線段組成。
利用圖形上下文將繪製的全部內容渲染顯示到view上面
也能夠:
利用UIKit封裝的繪圖函數直接繪圖
複製代碼
關於drawRect:spa
爲何要實現drawRect:方法才能繪圖到view上?
由於在drawRect:方法中才能取得跟view相關聯的圖形上下文
drawRect:方法在何時被調用?
當view第一次顯示到屏幕上時(被加到UIWindow上顯示出來)
調用view的setNeedsDisplay或者setNeedsDisplayInRect:時
在drawRect:方法中取得上下文後,就能夠繪製東西到view上
View內部有個layer(圖層)屬性,drawRect:方法中取得的是一個Layer Graphics Context,所以,繪製的東西實際上是繪製到view的layer上去了
View之因此能顯示東西,徹底是由於它內部的layer
複製代碼
//一些經常使用方法
//獲取上下文對象
let context = UIGraphicsGetCurrentContext()
//線條顏色
context?.setStrokeColor(UIColor.red.cgColor)
//線條寬度
context?.setLineWidth(1.0)
//移動畫筆到某一點
context?.move(to: CGPoint(x: 10, y: 10))
//畫線
context?.addLine(to: CGPoint(x: gameSize , y: 10))
//畫弧線 (方法1 ,這個方法若是畫一個完整的圓的話,
//有起始點的時候,只會鏈接起始點和重點,不會出現圓的軌跡!)
context?.addArc(center: CGPoint.init(x: 150, y: 100), radius: 30, startAngle: 0, endAngle: CGFloat(M_PI*2), clockwise: true);
複製代碼
context?.addArc(center: CGPoint.init(x: 150, y: 100), radius: 30, startAngle: 0, endAngle: CGFloat(M_PI), clockwise: true);
複製代碼
//畫圓弧 (方法2)
context?.addArc(tangent1End: CGPoint(x: 50, y: 50), tangent2End: CGPoint(x: 100, y: 50), radius: 50)
//二次貝塞爾曲線
context?.addQuadCurve(to: CGPoint.init(x: 150, y: 150), control: CGPoint.init(x: 50, y: 100))
//三次貝塞爾曲線
context?.addCurve(to: CGPoint.init(x: 250, y: 150), control1: CGPoint.init(x: 50, y: 100), control2: CGPoint.init(x: 100, y: 150))
//設置填充顏色
context?.setFillColor(UIColor.brown.cgColor);
//繪製矩形
context?.fill(CGRect.init(x: 50, y: 50, width: 100, height: 50));
//繪製橢圓
context?.strokeEllipse(in: CGRect.init(x: 50, y: 50, width: 100, height: 50));
//旋轉
context?.rotate(by: CGFloat.pi * 0.3)
//若是是須要使用矩陣變換(如平移,縮放,旋轉等),須要把添加路徑放到後面
//也就是須要把路徑添加進加入上下文以前進行,
context?.addArc(center: CGPoint(x: 50, y: 50), radius: 50, startAngle: 0, endAngle: CGFloat.pi, clockwise: true)
//繪製
context?.drawPath(using: .stroke)
複製代碼
上下文棧rest
1.入棧context?.saveGState()
2.出棧context?.restoreGState()
3.若是出戰的次數大於入棧,就會奔潰
4.什麼是入棧?就是拷貝當前圖形上下文,而後放到棧中, 只使用一個CGContextRef的話,須要不少修改上下文屬性(顏色,線寬等)的重複代碼,因此能夠保存當前上下文屬性進入棧中
5.如何理解拷貝圖形上下文,咱們操做的圖形上下文成爲A,此時若是圖形上下文就設置了context?.setStrokeColor(UIColor.green.cgColor)這一個屬性,入棧(咱們把拷貝後入棧的成爲B),而後咱們繼續操做當前上下文(如今稱爲 B),可是咱們出棧 A, 當前上下文的樣式都是隻有一個context?.setStrokeColor(UIColor.green.cgColor)的狀態!說白了,就是保存某種圖形上下文的狀態!
5.出棧的上下文,將樣式賦值給當前樣式,而後釋放
複製代碼
出棧入棧參考自 王鑫20111 的 https://www.jianshu.com/p/604b386d0468code