Quartz2D

什么是Quartz2D?

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

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

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

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

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

圖形上下文

context.png

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

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

drawRect:

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

drawRect:中取得的上下文

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

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

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

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

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

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

自定義view

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

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

自定義view的步驟:

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

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

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

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

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

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

  • 添加一個(gè)圓弧
    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一份,保存到棧頂(那個(gè)棧叫做”圖形上下文椛谄海”)
    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. 渲染上下文

記渍С:所有的繪圖当编,都是這個(gè)步驟,即使使用貝塞爾路徑徒溪,也只是對(duì)這個(gè)步驟進(jìn)行了封裝忿偷。對(duì)于繪圖而言金顿,拿到上下文很關(guān)鍵。

貝塞爾路徑

就是UIKit框架中鲤桥,對(duì)繪圖的封裝揍拆。實(shí)際操作起來,使用貝塞爾路徑芜壁,更為方便礁凡。

  • 用法與CGContextRef類似,但是oc對(duì)其進(jìn)行了封裝慧妄,更加面向?qū)ο蟆?/li>
  • 常用的方法:
    • 返回一個(gè)描述橢圓的路徑:
      + (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;

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

    貝塞爾曲線

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

    畫圓的角度及方向

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

裁剪核心代碼

// 開啟一個(gè)位圖(圖片)上下文 
//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ū)域饱普,再裁剪运挫,才會(huì)有效果)
[image drawAtPoint:CGPointZero];

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

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

截屏核心代碼

// 開啟一個(gè)跟屏幕一樣大的尺寸的上下文
          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();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贿条,一起剝皮案震驚了整個(gè)濱河市淋纲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌思灰,老刑警劉巖康愤,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件儡循,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡征冷,警方通過查閱死者的電腦和手機(jī)择膝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來检激,“玉大人肴捉,你說我怎么就攤上這事∈迨眨” “怎么了每庆?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)今穿。 經(jīng)常有香客問我,道長(zhǎng)伦籍,這世上最難降的妖魔是什么蓝晒? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任腮出,我火速辦了婚禮,結(jié)果婚禮上芝薇,老公的妹妹穿的比我還像新娘胚嘲。我一直安慰自己,他們只是感情好洛二,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布馋劈。 她就那樣靜靜地躺著,像睡著了一般晾嘶。 火紅的嫁衣襯著肌膚如雪妓雾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天垒迂,我揣著相機(jī)與錄音械姻,去河邊找鬼。 笑死机断,一個(gè)胖子當(dāng)著我的面吹牛楷拳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吏奸,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼欢揖,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了奋蔚?” 一聲冷哼從身側(cè)響起她混,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎旺拉,沒想到半個(gè)月后产上,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蛾狗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年晋涣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沉桌。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谢鹊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出留凭,到底是詐尸還是另有隱情佃扼,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布蔼夜,位于F島的核電站兼耀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瘤运,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一窍霞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拯坟,春花似錦但金、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至梦裂,卻和暖如春似枕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背塞琼。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工菠净, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人彪杉。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓毅往,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親派近。 傳聞我的和親對(duì)象是個(gè)殘疾皇子攀唯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Quartz2D以及drawRect的重繪機(jī)制字?jǐn)?shù)1487 閱讀21 評(píng)論1 喜歡1一、什么是Quartz2D Q...
    PurpleWind閱讀 760評(píng)論 0 3
  • 什么是Quartz2D 是一個(gè)二維的繪圖引擎,同時(shí)支持iOS和Mac系統(tǒng) Quartz2D的API是純C語言的,它...
    Mario_ZJ閱讀 574評(píng)論 0 1
  • 一戒幔、Paths (路徑) 路徑定義了一個(gè)或多個(gè)形狀或子路徑。子路徑可以由直線土童、曲線或兩者兼而有之诗茎,它可以是打開的或...
    尋形覓影閱讀 1,049評(píng)論 1 5
  • 什么是Quartz2D? 簡(jiǎn)單來說,Quartz2D是用C語言封裝的二維繪圖引擎献汗,同時(shí)支持iOS和Mac系統(tǒng)敢订,利用...
    enoughpower閱讀 729評(píng)論 1 2
  • 簡(jiǎn)述: 1、Quartz2D是什么Quartz2D是二維繪圖引擎罢吃,同時(shí)支持IOS和Mac 2楚午、Quartz2D能做...
    LitterL閱讀 635評(píng)論 0 6