Quartz 2D 在 Swift 中的使用

Quartz 2D是一個二維繪圖引擎,同時支持iOS和Mac系統。 其實 iOS 中不少控件都是經過 Quartz 2D 畫出來的. 同時Quartz 2D還能夠作這些事情,swift

一、剪裁圖形
二、塗鴉/畫板(如簽名等)
三、手勢解鎖(連線)
四、折線圖、餅狀圖、柱形圖等繪製(雖然我都是直接用 charts)
複製代碼

使用 Quartz 2D繪圖的核心步驟:bash

一、得到上下文
二、繪製/拼接繪圖路徑
三、將路徑添加到上下文
四、渲染上下文
記住:全部的繪圖,都是這個步驟,即便使用貝塞爾路徑,也只是對這個步驟進行了封裝。
對於繪圖而言,拿到上下文很關鍵。
複製代碼

其中圖形上下文有五種 函數

WechatIMG2009.jpeg

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);
複製代碼

使用這個方法畫完整圓.jpeg

context?.addArc(center: CGPoint.init(x: 150, y: 100), radius: 30, startAngle: 0, endAngle: CGFloat(M_PI), clockwise: true);
複製代碼

若是弧度爲180度就沒有這個問題.jpeg

//畫圓弧 (方法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

相關文章
相關標籤/搜索