Quartz2D?

什么是Quartz2D?

Quartz 2D是一個二維繪圖引擎,同時支持iOS和Mac系統(tǒng)

  • Quartz 2D能完成的工作
    • 繪制圖形 : 線條\三角形\矩形\圓\弧等
    • 繪制文字
    • 繪制\生成圖片(圖像)
    • 讀取\生成PDF
    • 截圖\裁剪圖片
    • 自定義UI控件

Quartz2D在iOS開發(fā)中的價值:

  • 繪制一些系統(tǒng)UIKit框架中不好展示的內(nèi)容,例如餅圖
  • 自定義一些控件
  • 不添加UI控件的情況下,使UI內(nèi)容更豐富
  • ……

iOS中,大部分控件都是Quartz2D繪制出來的

圖形上下文

[圖片上傳失敗...(image-534e23-1521165872369)]

圖形上下文就相當(dāng)于畫布,不同類型的畫布就是決定著畫得內(nèi)容將展示在哪里。

  • Quartz2D提供了以下幾種類型的Graphics Context:
    • Bitmap Graphics Context 位圖上下文,在這個上下文上繪制或者渲染的內(nèi)容,可以獲取成圖片(需要主動創(chuàng)建一個位圖上下文來使用,使用完畢,一定要銷毀)
    • PDF Graphics Context
    • Window Graphics Context
    • Layer Graphics Context 圖層上下文,針對UI控件的上下文
    • Printer Graphics Context

drawRect:

為什么要實(shí)現(xiàn)drawRect:方法才能繪圖到view上?
因?yàn)樵赿rawRect:方法中才能取得跟view相關(guān)聯(lián)的圖形上下文

drawRect:中取得的上下文

在drawRect:方法中取得上下文后,就可以繪制東西到view上

View內(nèi)部有個layer(圖層)屬性,drawRect:方法中取得的是一個Layer Graphics Context,因此,繪制的東西其實(shí)是繪制到view的layer上去了

View之所以能顯示東西,完全是因?yàn)樗鼉?nèi)部的layer

drawRect:方法的調(diào)用?

  • 當(dāng)view第一次顯示到屏幕上時,系統(tǒng)會創(chuàng)建好一個跟當(dāng)前view相關(guān)的Layer上下文
  • 系統(tǒng)會通過此上下文,在drawRect:方法中繪制好當(dāng)前view的內(nèi)容
  • 主動讓view重繪內(nèi)容的時候,調(diào)用setNeedsDisplay或者setNeedsDisplayInRect:。我們主動調(diào)用drawRect:方法是無效的。
  • 調(diào)用view的setNeedsDisplay或者setNeedsDisplayInRect:時。
  • 注意:setNeedsDisplay和setNeedsDisplayInRect:方法調(diào)用后,屏幕并不是立即刷新,而是會在下一次刷新屏幕的時候把繪制的內(nèi)容顯示出來。

也正是系統(tǒng)會在調(diào)用這個方法之前創(chuàng)建一個與該view相關(guān)的上下文,才讓我們可以在drawRect:方法中繪制。注意:在其他地方拿不到view相關(guān)的上下文,所以不能實(shí)現(xiàn)繪制。

自定義view

如何利用Quartz2D繪制東西到view上?

  • 首先,得有圖形上下文,因?yàn)樗鼙4胬L圖信息,并且決定著繪制到什么地方去
  • 其次,那個圖形上下文必須跟view相關(guān)聯(lián),才能將內(nèi)容繪制到view上面

自定義view的步驟:

  1. 新建一個類,繼承自UIView
  2. 實(shí)現(xiàn)- (void)drawRect:(CGRect)rect方法,然后在這個方法中
  3. 取得跟當(dāng)前view相關(guān)聯(lián)的圖形上下文
  4. 繪制相應(yīng)的圖形內(nèi)容
  5. 利用圖形上下文將繪制的所有內(nèi)容渲染顯示到view上面

常用拼接路徑函數(shù)

  • 獲取上下文
    CGContextRef triangle = UIGraphicsGetCurrentContext();

  • 新建一個起點(diǎn)
    void CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)

  • 添加新的線段到某個點(diǎn)
    void CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)

  • 添加一個矩形
    void CGContextAddRect(CGContextRef c, CGRect rect)

  • 添加一個橢圓
    void CGContextAddEllipseInRect(CGContextRef context, CGRect rect)

  • 添加一個圓弧
    void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)

常用繪制路徑函數(shù)

  • Mode參數(shù)決定繪制的模式
    void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)

  • 繪制空心路徑
    void CGContextStrokePath(CGContextRef c)

  • 繪制實(shí)心路徑
    void CGContextFillPath(CGContextRef c)

提示:一般以CGContextDraw、CGContextStroke、CGContextFill開頭的函數(shù),都是用來繪制路徑的

圖形上下文棧的操作

  • 將當(dāng)前的上下文copy一份,保存到棧頂(那個棧叫做”圖形上下文?!?
    void CGContextSaveGState(CGContextRef c)

  • 將棧頂?shù)纳舷挛某鰲?替換掉當(dāng)前的上下文
    void CGContextRestoreGState(CGContextRef c)

矩陣操作

利用矩陣操作,能讓繪制到上下文中的所有路徑一起發(fā)生變化

  • 縮放
    void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)

  • 旋轉(zhuǎn)
    void CGContextRotateCTM(CGContextRef c, CGFloat angle)

  • 平移
    void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)

繪圖的核心步驟:

  1. 獲得上下文
  2. 繪制/拼接繪圖路徑
  3. 將路徑添加到上下文
  4. 渲染上下文

記?。核械睦L圖,都是這個步驟,即使使用貝塞爾路徑,也只是對這個步驟進(jìn)行了封裝。對于繪圖而言,拿到上下文很關(guān)鍵。

貝塞爾路徑

就是UIKit框架中,對繪圖的封裝。實(shí)際操作起來,使用貝塞爾路徑,更為方便。

  • 用法與CGContextRef類似,但是oc對其進(jìn)行了封裝,更加面向?qū)ο蟆?/li>
  • 常用的方法:
    • 返回一個描述橢圓的路徑:
      + (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect;

    • 設(shè)置起始點(diǎn):
      - (void)moveToPoint:(CGPoint)point;

    • 添加直線到一點(diǎn):
      - (void)addLineToPoint:(CGPoint)point;

    • 三次貝塞爾曲線:
      - (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;

[圖片上傳失敗...(image-f06941-1521165872367)]

  • 貝塞爾曲線:
    - (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;

    [圖片上傳失敗...(image-c02bb8-1521165872365)]

  • 繪制圓弧:
    - (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

    [圖片上傳失敗...(image-26cc2-1521165872365)]

  • 封閉閉路徑:- (void)closePath;

裁剪核心代碼

// 開啟一個位圖(圖片)上下文 
//size:上下文尺寸
//opaque:不透明。一般是透明的,所以設(shè)置為NO
//scale:縮放,如果不縮放,設(shè)置為0就好
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);

// 描述圓形的路徑
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)];

// 把圓形路徑設(shè)置裁剪區(qū)域(將區(qū)域外的內(nèi)容裁剪掉,是現(xiàn)實(shí)區(qū)域內(nèi)的內(nèi)容)
[path addClip];

// 繪制圖片(先設(shè)置裁剪區(qū)域,再裁剪,才會有效果)
[image drawAtPoint:CGPointZero];

// 從上下文中內(nèi)容生成一張圖片
image = UIGraphicsGetImageFromCurrentImageContext();

// 關(guān)閉上下文(一定不要忘了關(guān)閉自己開啟的上下文)
UIGraphicsEndImageContext();

截屏核心代碼

// 開啟一個跟屏幕一樣大的尺寸的上下文
          UIGraphicsBeginImageContextWithOptions(caputeView.bounds.size, NO, 0);

// 獲取自己創(chuàng)建的位圖上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();

// view之所以你能顯示內(nèi)容,是因?yàn)橛袌D層,因此只要把圖層畫到上下文
// 圖層只能渲染,不能繪制
[caputeView.layer renderInContext:ctx];

// 從上下文中生成一張新的圖片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

// 關(guān)閉上下文
UIGraphicsEndImageContext();

作者:Ljson
鏈接:http://www.itdecent.cn/p/0e785269dccc
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Quartz2D以及drawRect的重繪機(jī)制字?jǐn)?shù)1487 閱讀21 評論1 喜歡1一、什么是Quartz2D Q...
    PurpleWind閱讀 916評論 0 3
  • 一、簡介 對于 Core Graphics Framework,可以從兩個方面初步感知,一是它在繪圖系統(tǒng)中的...
    kReader閱讀 1,900評論 0 1
  • 什么是Quartz2D? Quartz 2D是一個二維繪圖引擎,同時支持iOS和Mac系統(tǒng) Quartz 2D能完...
    Ljson閱讀 11,615評論 2 83
  • 什么是Quartz2D 是一個二維的繪圖引擎,同時支持iOS和Mac系統(tǒng) Quartz2D的API是純C語言的,它...
    Mario_ZJ閱讀 663評論 0 1
  • 12.4. 不是滋味 有時候覺得不爽,不快樂,不幸福,卻又說不出啥滋味……師父說,人生很多煩惱,就來自于“不是滋味...
    陌上花開wen閱讀 360評論 0 3

友情鏈接更多精彩內(nèi)容