UIView渲染機(jī)制及繪制方法

一填帽、drawRect

這個(gè)方法是用來重繪的评也,一般為了降低視圖層級(jí)瞳脓,會(huì)選擇在這里進(jìn)行繪制悔政。

  • drawRect在以下情況下會(huì)被調(diào)用:
  1. 如果在UIView初始化時(shí)沒有設(shè)置rect大小,將直接導(dǎo)致drawRect不被自動(dòng)調(diào)用桥言。drawRect調(diào)用是在Controller->loadView,Controller->viewDidLoad兩方法之后調(diào)用的.所以不用擔(dān)心在控制器中,這些View的drawRect就開始畫了.這樣可以在控制器中設(shè)置一些值給View(如果這些View draw的時(shí)候需要用到某些變量值).
  2. 該方法在調(diào)用sizeToFit后被調(diào)用萌踱,所以可以先調(diào)用sizeToFit計(jì)算出size。然后系統(tǒng)自動(dòng)調(diào)用drawRect:方法号阿。
  3. 通過設(shè)置contentMode屬性值為UIViewContentModeRedraw并鸵。那么將在每次設(shè)置或更改frame的時(shí)候自動(dòng)調(diào)用drawRect:
  4. 直接調(diào)用setNeedsDisplay扔涧,或者setNeedsDisplayInRect:觸發(fā)drawRect:园担,但是有個(gè)前提條件是rect不能為0。

以上1,2推薦枯夜;而3,4不提倡

使用注意點(diǎn):

  1. 若使用UIView繪圖弯汰,只能在drawRect:方法中獲取相應(yīng)的contextRef并繪圖。如果在其他方法中獲取將獲取到一個(gè)invalidate的ref并且不能用于畫圖湖雹。drawRect:方法不能手動(dòng)顯示調(diào)用咏闪,必須通過調(diào)用setNeedsDisplay 或者 setNeedsDisplayInRect,讓系統(tǒng)自動(dòng)調(diào)該方法摔吏。
  2. 若使用CALayer繪圖鸽嫂,只能在drawInContext:中(類似于drawRect)繪制,或者在delegate中的相應(yīng)方法繪制征讲。同樣也是調(diào)用setNeedDisplay等間接調(diào)用以上方法
  3. 若要實(shí)時(shí)畫圖据某,不能使用gestureRecognizer,只能使用touchbegan等方法來掉用setNeedsDisplay實(shí)時(shí)刷新屏幕.
  4. 繪圖時(shí)一定是layout之后稳诚,不必?fù)?dān)心frame的問題
  • sizeToFit
- (void)sizeToFit 
根據(jù)子視圖的大小位置哗脖,調(diào)整視圖,使其恰好圍繞子視圖, 也就是說自動(dòng)適應(yīng)子視圖的大小才避,只顯示子視圖
- (CGSize)sizeThatFits:(CGSize)size
讓視圖計(jì)算最適合子視圖的大小橱夭,即能把全部子視圖顯示出來所需要的最小的size
  1. sizeToFit不應(yīng)該在子類中被重寫,應(yīng)該重寫sizeThatFits桑逝。sizeToFit會(huì)自動(dòng)調(diào)用sizeThatFits方法棘劣;
  2. sizeThatFits傳入的參數(shù)是receiver當(dāng)前的size,返回一個(gè)適合的size
  3. sizeToFit可以被手動(dòng)直接調(diào)用sizeToFitsizeThatFits方法都沒有遞歸楞遏,對(duì)subviews也不負(fù)責(zé)茬暇,只負(fù)責(zé)自己

重繪

-drawRect:(CGRect)rect方法:重寫此方法预鬓,執(zhí)行重繪任務(wù) 
-setNeedsDisplay方法:標(biāo)記為需要重繪,異步調(diào)用drawRect 
-setNeedsDisplayInRect:(CGRect)invalidRect方法:標(biāo)記為需要局部重繪 

layoutSubviews對(duì)subviews重新布局 
layoutSubviews方法調(diào)用先于drawRect 
setNeedsLayout在receiver標(biāo)上一個(gè)需要被重新布局的標(biāo)記沧奴,在系統(tǒng)runloop的下一個(gè)周期自動(dòng)調(diào)用layoutSubviews 
layoutIfNeeded方法如其名滔吠,UIKit會(huì)判斷該receiver是否需要layout.根據(jù)Apple官方文檔,layoutIfNeeded方法應(yīng)該是這樣的 
layoutIfNeeded遍歷的不是superview鏈肆资,應(yīng)該是subviews鏈 
drawRect是對(duì)receiver的重繪犯犁,能獲得context。 

總之,理解view布局的過程入桂,可以幫助你理解View顯示的相關(guān)問題蜘腌,解決一些界面問題倘潜,合理使用以上方法對(duì)你自定義控件也有很大的幫助。

-drawRect:(CGRect)rect方法:重寫此方法澜掩,執(zhí)行重繪任務(wù)
-setNeedsDisplay方法:標(biāo)記為需要重繪乔妈,異步調(diào)用drawRect
-setNeedsDisplayInRect:(CGRect)invalidRect方法:標(biāo)記為需要局部重繪

sizeToFit會(huì)自動(dòng)調(diào)用sizeThatFits方法;
sizeToFit不應(yīng)該在子類中被重寫氓皱,應(yīng)該重寫sizeThatFits
sizeThatFits傳入的參數(shù)是receiver當(dāng)前的size路召,返回一個(gè)適合的size
sizeToFit可以被手動(dòng)直接調(diào)用
sizeToFit和sizeThatFits方法都沒有遞歸勃刨,對(duì)subviews也不負(fù)責(zé),只負(fù)責(zé)自己

layoutSubviews對(duì)subviews重新布局
layoutSubviews方法調(diào)用先于drawRect
setNeedsLayout在receiver標(biāo)上一個(gè)需要被重新布局的標(biāo)記股淡,在系統(tǒng)runloop的下一個(gè)周期自動(dòng)調(diào)用layoutSubviews
layoutIfNeeded方法如其名身隐,UIKit會(huì)判斷該receiver是否需要layout
layoutIfNeeded遍歷的不是superview鏈,應(yīng)該是subviews鏈
drawRect是對(duì)receiver的重繪揣非,能獲得context

setNeedDisplay在receiver標(biāo)上一個(gè)需要被重新繪圖的標(biāo)記抡医,在下一個(gè)draw周期自動(dòng)重繪iPhone device的刷新頻率是60hz,也就是1/60秒后重繪

簡(jiǎn)單使用

先畫一條線

- (void)drawRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();                   //獲取當(dāng)前繪制環(huán)境
    CGContextSetLineWidth(ctx, 2);                                      //設(shè)置線條寬度
    CGContextSetStrokeColorWithColor(ctx, [[UIColor redColor] CGColor]);//設(shè)置線條顏色
    CGContextBeginPath(ctx);                                            //開始配置繪制路徑
    CGContextMoveToPoint(ctx, 100, 100);                                //設(shè)置起點(diǎn)為(100,100)
    CGContextAddLineToPoint(ctx, 200, 200);                             //添加一個(gè)直線到點(diǎn)(200,200)
    CGContextDrawPath(ctx, kCGPathStroke);                              //繪制路徑
}
效果圖

這里分為兩部分:

  1. 獲取當(dāng)前上下文并設(shè)置相關(guān)設(shè)置
    UIGraphicsGetCurrentContext()用來獲取當(dāng)前繪制環(huán)境早敬,只能在drawRect里面獲取該上下文忌傻。
    這里設(shè)置了線條寬度為2,線條顏色為紅色搞监。
  2. 繪制路徑
    繪制路徑要以CGContextBeginPath()開始水孩。
    直線、弧琐驴、曲線開始于當(dāng)前點(diǎn)俘种。空路徑?jīng)]有當(dāng)前點(diǎn),我們必須調(diào)用CGContextMoveToPoint來設(shè)置第一個(gè)子路徑的起始點(diǎn)绝淡,或者調(diào)用一個(gè)便利函數(shù)來隱式地完成該任務(wù)宙刘。
    最后使用CGContextStrokePath()繪制,也可以使用CGContextDrawPath()選擇繪制方法牢酵。

設(shè)置上下文的屬性

CGContextRef狀態(tài)

//保存CGContextRef當(dāng)前的繪圖狀態(tài)悬包,方便以后恢復(fù)該狀態(tài)。CGContextSaveGState()函數(shù)保存的繪圖狀態(tài)馍乙,不僅包括當(dāng)前坐標(biāo)系統(tǒng)的狀態(tài)布近,也包括當(dāng)前設(shè)置的填充風(fēng)格、線條風(fēng)格丝格、陰影風(fēng)格等各種繪圖狀態(tài)撑瞧。但 CGContextSaveGState()函數(shù)不會(huì)保存當(dāng)前繪制的圖形
void CGContextSaveGState(CGContextRef__nullable c) 

//把CGContextRef的狀態(tài)恢復(fù)到最近一次保存時(shí)的狀態(tài)
void CGContextRestoreGState(CGContextRef__nullable c)

坐標(biāo)空間和變化
UIKit是iPhone SDK的Cocoa Touch層的核心framework,是iPhone應(yīng)用程序圖形界面和事件驅(qū)動(dòng)的基礎(chǔ)显蝌,它和傳統(tǒng)的windows桌面一樣预伺,坐標(biāo)系是y軸向下的; Core Graphics(Quartz)一個(gè)基于2D的圖形繪制引擎,它的坐標(biāo)系則是y軸向上的曼尊;而OpenGL ES是iPhone SDK的2D和3D繪制引擎扭屁,它使用左手坐標(biāo)系,它的坐標(biāo)系也是y軸向上的涩禀,如果不考慮z軸,在二維下它的坐標(biāo)系和Quartz是一樣的然眼。

//縮放坐標(biāo)系統(tǒng)
該方法控制坐標(biāo)系統(tǒng)水平方向上縮放 sx艾船,垂直方向上縮放 sy。在縮放后的坐標(biāo)系統(tǒng)上繪制圖形時(shí),所有點(diǎn)的 X 坐標(biāo)都相當(dāng)于乘以 sx 因子屿岂,所有點(diǎn)的 Y 坐標(biāo)都相當(dāng)于乘以 sy因子践宴。
void CGContextScaleCTM(CGContextRef__nullable c, CGFloat sx, CGFloat sy)

//平移坐標(biāo)系統(tǒng)
 該方法相當(dāng)于把原來位于 (0, 0) 位置的坐標(biāo)原點(diǎn)平移到 (tx, ty)點(diǎn)。在平移后的坐標(biāo)系統(tǒng)上繪制圖形時(shí)爷怀,所有坐標(biāo)點(diǎn)的 X坐標(biāo)都相當(dāng)于增加了 tx阻肩,所有點(diǎn)的 Y坐標(biāo)都相當(dāng)于增加了 ty。
void CGContextTranslateCTM(CGContextRef__nullable c,
    CGFloat tx, CGFloat ty)

//旋轉(zhuǎn)坐標(biāo)系統(tǒng)
 該方法控制坐標(biāo)系統(tǒng)旋轉(zhuǎn) angle 弧度运授。在縮放后的坐標(biāo)系統(tǒng)上繪制圖形時(shí)烤惊,所有坐標(biāo)點(diǎn)的 X、Y坐標(biāo)都相當(dāng)于旋轉(zhuǎn)了 angle弧度之后的坐標(biāo)吁朦。
void CGContextRotateCTM(CGContextRef__nullable c, CGFloat angle)

//使用 transform變換矩陣對(duì) CGContextRef的坐標(biāo)系統(tǒng)執(zhí)行變換柒室,通過使用坐標(biāo)矩陣可以對(duì)坐標(biāo)系統(tǒng)執(zhí)行任意變換。
void CGContextConcatCTM(CGContextRef__nullable c,
    CGAffineTransform transform)

//獲取CGContextRef的坐標(biāo)系統(tǒng)的變換矩陣
CGAffineTransform CGContextGetCTM(CGContextRef__nullable c)

繪圖屬性設(shè)置相關(guān)函數(shù)

//設(shè)置繪制直線逗宜、邊框時(shí)的線條寬度
void CGContextSetLineWidth(CGContextRef__nullable c, CGFloat width)

//設(shè)置線段端點(diǎn)的繪制形狀雄右。該屬性支持如下三個(gè)值。
typedef CF_ENUM(int32_t, CGLineCap) {
    kCGLineCapButt, //沒有端點(diǎn)纺讲,線條結(jié)尾處直接結(jié)束擂仍,這是默認(rèn)值。
    kCGLineCapRound,//圓形端點(diǎn)熬甚,線條結(jié)尾處繪制一個(gè)直徑為線條寬度的半圓逢渔。
    kCGLineCapSquare//方形端點(diǎn)。線條結(jié)尾處繪制半個(gè)邊長(zhǎng)為線條寬度的正方形则涯。需要說明的是复局,這種形狀的端點(diǎn)與“butt”形狀的端點(diǎn)十分相似,只是采用這種形式的端點(diǎn)的線條略長(zhǎng)一點(diǎn)而已
};
void CGContextSetLineCap(CGContextRef__nullable c, CGLineCap cap)

typedef CF_ENUM(int32_t, CGLineJoin) {
    kCGLineJoinMiter, // 這是默認(rèn)的屬性值粟判。該方格的連接點(diǎn)形狀如圖1所示亿昏。
    kCGLineJoinRound, // 稍微圓角, 該方格的連接點(diǎn)形狀如圖2所示。
    kCGLineJoinBevel  // 斜角,該方格的連接點(diǎn)形狀如圖3所示档礁。
};
//設(shè)置線條連接點(diǎn)的風(fēng)格角钩,該屬性支持如上三個(gè)值:
void CGContextSetLineJoin(CGContextRef__nullable c, CGLineJoin join)

//當(dāng)把連接點(diǎn)風(fēng)格設(shè)為meter風(fēng)格時(shí),該方法用于控制銳角箭頭的長(zhǎng)度*/
void CGContextSetMiterLimit(CGContextRef__nullable c, CGFloat limit)
圖1 圖2 圖3
kCGLineJoinMiter
kCGLineJoinRound
kCGLineJoinBevel
/* 
 Linedash pattern(虛線模式)允許我們沿著描邊繪制虛線呻澜。我們通過在CGContextSetLineDash結(jié)構(gòu)體中指定虛線數(shù)組和虛線相位來控制虛線的大小及位置递礼。
其中l(wèi)engths屬性指定了虛線段的長(zhǎng)度,該值是在繪制片斷與未繪制片斷之間交替(實(shí)線羹幸、空白脊髓、實(shí)線、空白栅受、實(shí)線....)将硝。phase屬性指定虛線模式的起始點(diǎn)恭朗,phase實(shí)際是虛線中實(shí)線長(zhǎng)度的余數(shù),當(dāng)phase<length時(shí)向左偏移phase%length依疼,phase>length向右偏移phase%length痰腮,phase或phase%length為0時(shí)不偏移。
*/
void CGContextSetLineDash(CGContextRef__nullable c, CGFloat phase,const CGFloat *__nullable lengths, size_t count)
注意:CGContextSetLineDash的使用需要在存在路徑的基礎(chǔ)上律罢。
虛線

其他設(shè)置

//設(shè)置彎曲的路徑中的圖形上下文的準(zhǔn)確性膀值。
void CGContextSetFlatness(CGContextRef__nullable c, CGFloat flatness)

//設(shè)置全局透明度
void CGContextSetAlpha(CGContextRef__nullable c, CGFloat alpha)

//設(shè)置CGContextRef的疊加模式。Quartz 2D支持多種疊加模
void CGContextSetBlendMode(CGContextRef __nullable c, CGBlendMode mode)

繪制路徑

繪制路徑要以CGContextBeginPath()開始误辑。

//開始創(chuàng)建路徑.
void CGContextBeginPath(CGContextRef__nullable c)

//開始一個(gè)新的子路徑點(diǎn)
void CGContextMoveToPoint(CGContextRef__nullable c,
    CGFloat x, CGFloat y)

//添加一條直線段從當(dāng)前指向的(x,y)
void CGContextAddLineToPoint(CGContextRef__nullable c,
    CGFloat x, CGFloat y)

/**
 *  從當(dāng)前添加一個(gè)三次Bezier曲線
 *  @param cp1x 控制點(diǎn)1 x坐標(biāo)
 *  @param cp1y 控制點(diǎn)1 y坐標(biāo)
 *  @param cp2x 控制點(diǎn)2 x坐標(biāo)
 *  @param cp2y 控制點(diǎn)2 y坐標(biāo)
 *  @param x    直線的終點(diǎn) x坐標(biāo)
 *  @param y    直線的終點(diǎn) y坐標(biāo)
 */
void CGContextAddCurveToPoint(CGContextRef__nullable c, CGFloat cp1x, CGFloat cp1y, CGFloat cp2x, CGFloat cp2y, CGFloat x, CGFloat y)    

/**
 *  從當(dāng)前添加一個(gè)二次Bezier曲線
 *  @param cpx 控制點(diǎn) x坐標(biāo)
 *  @param cpy 控制點(diǎn) y坐標(biāo)
 *  @param x   直線的終點(diǎn) x坐標(biāo)
 *  @param y   直線的終點(diǎn) y坐標(biāo)
 */
void CGContextAddQuadCurveToPoint(CGContextRef__nullable c, CGFloat cpx, CGFloat cpy,CGFloat x,CGFloat y)

//關(guān)閉當(dāng)前上下文的子路徑,且當(dāng)前點(diǎn)和起點(diǎn)連接起來(需要在繪制之前調(diào)用)
void CGContextClosePath(CGContextRef__nullable c)

//添加一個(gè)矩形路徑
void CGContextAddRect(CGContextRef__nullable c, CGRect rect)

//添加多個(gè)矩形路徑
void CGContextAddRects(CGContextRef__nullable c,
    const CGRect * __nullable rects, size_t count)

//添加多條直線路徑
void CGContextAddLines(CGContextRef__nullable c,
    const CGPoint * __nullable points, size_t count)

//根據(jù)一個(gè)矩形,繪制橢圓(圓形)
void CGContextAddEllipseInRect(CGContextRef__nullable c, CGRect rect)

/**
 *  添加弧形路徑
 *  @param x          中心點(diǎn)x坐標(biāo)
 *  @param y          中心點(diǎn)y坐標(biāo)
 *  @param radius     半徑
 *  @param startAngle 起始弧度
 *  @param endAngle   終止弧度
 *  @param clockwise  是否逆時(shí)針繪制沧踏,1逆時(shí)針,0順時(shí)針
 */
void CGContextAddArc(CGContextRef__nullable c, CGFloat x,CGFloat y,CGFloat radius,CGFloat startAngle,CGFloat endAngle,int clockwise)

//這個(gè)函數(shù)使用一個(gè)序列的三次貝塞爾曲線創(chuàng)建一個(gè)弧 原理:首先畫兩條線稀余,這兩條線分別是 current point to (x1,y1)和(x1,y1) to (x2,y2).這樣就是出現(xiàn)一個(gè)以(x1,y1)為頂點(diǎn)的兩條射線悦冀,然后定義半徑長(zhǎng)度,這個(gè)半徑是垂直于兩條射線的睛琳,這樣就能決定一個(gè)圓了盒蟆,如果當(dāng)前點(diǎn)和第一個(gè)切點(diǎn)的弧(起點(diǎn))是不平等的,那么會(huì)添加一條直線段從當(dāng)前指向第一個(gè)切點(diǎn)∈ζ弧的終點(diǎn)成為新的當(dāng)前點(diǎn)的路徑
void CGContextAddArcToPoin(CGContextRef __nullable c, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius)
image
//添加路徑到圖形上下文
void CGContextAddPath(CGContextRef__nullable c, CGPathRef__nullable path)

繪制路徑

//使用繪制當(dāng)前路徑時(shí)覆蓋的區(qū)域作為當(dāng)前CGContextRef中的新路徑历等,一般配合CGContextClip使用
void CGContextReplacePathWithStrokedPath(CGContextRef__nullable c)

//當(dāng)前路徑是否包含任何的子路徑
(Bool)CGContextIsPathEmpty(CGContextRef__nullable c)

//返回一個(gè)非空的路徑中的當(dāng)前點(diǎn)
(CGPoint)CGContextGetPathCurrentPoint(CGContextRef__nullable c)

//返回包含當(dāng)前路徑的最小矩形
(CGRect)CGContextGetPathBoundingBox(CGContextRef__nullable c)

//返回當(dāng)前上下文的路徑的副本
(CGPathRef __nullable)CGContextCopyPath(CGContextRef__nullable c)

//檢查當(dāng)前路徑中是否包含指定的點(diǎn)
(Bool)CGContextPathContainsPoint(CGContextRef__nullable c,
    CGPoint point, CGPathDrawingMode mode)

繪制方式

typedef CF_ENUM (int32_t, CGPathDrawingMode) {
    kCGPathFill,        //填充
    kCGPathEOFill,      //奇偶填充(奇填偶不填)
    kCGPathStroke,      //描邊
    kCGPathFillStroke,  //描邊并填充
    kCGPathEOFillStroke //奇偶填充并描邊
};
kCGPathFill kCGPathEOFill kCGPathStroke kCGPathFillStroke kCGPathEOFillStroke
圖1
圖2
圖3
圖4
圖5
//使用指定模式繪制當(dāng)前CGContextRef中所包含的路徑。
void CGContextDrawPath(CGContextRef__nullable c, CGPathDrawingMode mode)

 //填充該路徑包圍的區(qū)域
void CGContextFillPath(CGContextRef__nullable c)

//使用奇偶規(guī)則來填充該路徑包圍的區(qū)域辟癌。奇偶規(guī)則指某個(gè)點(diǎn)被路徑包圍了奇數(shù)次則繪制該點(diǎn)寒屯,否則不繪制
void CGContextEOFillPath(CGContextRef__nullable c)

//使用當(dāng)前 CGContextRef設(shè)置的線寬繪制路徑
void CGContextStrokePath(CGContextRef__nullable c)

//填充rect代表的矩形
void CGContextFillRect(CGContextRef__nullable c, CGRect rect)

//填充多個(gè)矩形
void CGContextFillRects(CGContextRef__nullable c,
    const CGRect * __nullable rects, size_t count)

//使用當(dāng)前 CGContextRef設(shè)置的線寬繪制矩形框
void CGContextStrokeRect(CGContextRef__nullable c, CGRect rect)

//使用指定線寬繪制矩形框
void CGContextStrokeRectWithWidth(CGContextRef__nullable c,
    CGRect rect, CGFloat width)

//清除指定矩形區(qū)域上繪制的圖形
void CGContextClearRect(CGContextRef__nullable c, CGRect rect)

//填充rect矩形的內(nèi)切橢圓區(qū)域
void CGContextFillEllipseInRect(CGContextRef__nullable c,
    CGRect rect)

//使用當(dāng)前 CGContextRef設(shè)置的線寬繪制rect矩形的內(nèi)切橢圓
void CGContextStrokeEllipseInRect(CGContextRef__nullable c, CGRect rect)

/**
 *  使用當(dāng)前 CGContextRef   設(shè)置的線寬繪制多條線段
 *  @param c               當(dāng)前上下文
 *  @param points          線段數(shù)組(必須成對(duì)出現(xiàn),起點(diǎn)終點(diǎn)配對(duì))
 *  @param count           數(shù)組長(zhǎng)度
 */
void CGContextStrokeLineSegments(CGContextRef__nullable c,
    const CGPoint * __nullable points, size_t count)

//修改當(dāng)前剪貼路徑黍少,使用非零繞數(shù)規(guī)則
void CGContextClip(CGContextRef__nullable c)

//修改當(dāng)前剪貼路徑寡夹,使用奇偶規(guī)則
void CGContextEOClip(CGContextRef__nullable c)

//剪切遮罩處理(針對(duì)圖片)
void CGContextClipToMask(CGContextRef__nullable c, CGRect rect, CGImageRef__nullable mask)

//獲取到了需要繪制的圖形上下文的位置與大小
CGRect CGContextGetClipBoundingBox(CGContextRef__nullable c)

//剪切指定矩形區(qū)域外的部分
void CGContextClipToRect(CGContextRef__nullable c, CGRect rect)

//剪切指定多個(gè)矩形區(qū)域外的部分
void CGContextClipToRects(CGContextRef__nullable c,const CGRect *  rects, size_t count)

設(shè)置顏色

// 設(shè)置描邊和填充色為紅色
[[UIColor redColor] set]

// 設(shè)置填充色為綠色
[[UIColor greenColor] setFill]

// 設(shè)置描邊色為黃色
[[UIColor yellowColor] set]

//使用指定顏色來設(shè)置該CGContextRef的填充顏色
void CGContextSetFillColorWithColor(CGContextRef__nullable c,
    CGColorRef __nullable color)

//使用指定顏色來設(shè)置該CGContextRef的線條顏色
void CGContextSetStrokeColorWithColor(CGContextRef__nullable c,
    CGColorRef __nullable color)

//顏色空間填充
void CGContextSetFillColorSpace(CGContextRef__nullable c, CGColorSpaceRef__nullable space)

//設(shè)置線框顏色空間
void CGContextSetStrokeColorSpace(CGContextRef__nullable c,
    CGColorSpaceRef __nullable space)

//設(shè)置填充顏色空間 CGFloat redColor[4] = {1.0,0,0,1.0};
void CGContextSetFillColor(CGContextRef__nullable c,const CGFloat *__nullable components(redColor))

//設(shè)置畫筆顏色 CGFloat redColor[4] = {1.0,0,0,1.0};
void CGContextSetStrokeColor(CGContextRef__nullable c,const CGFloat *__nullable components(redColor))

//設(shè)置該CGContextRef使用位圖填充
void CGContextSetFillPattern(CGContextRef__nullable c, CGPatternRef__nullable pattern,const CGFloat * __nullable components)

//設(shè)置該CGContextRef使用位圖繪制線條、邊框
void CGContextSetStrokePattern(CGContextRef__nullable c, CGPatternRef__nullable pattern,const CGFloat * __nullable components)

//設(shè)置該CGContextRef采用位圖填充的相位
void CGContextSetPatternPhase(CGContextRef__nullable c, CGSize phase)

//使用灰色來設(shè)置該CGContextRef的填充顏色
void CGContextSetGrayFillColor(CGContextRef__nullable c,
    CGFloat gray, CGFloat alpha)

//使用灰色來設(shè)置該CGContextRef的線條顏色
void CGContextSetGrayStrokeColor(CGContextRef__nullable c,
    CGFloat gray, CGFloat alpha)

//使用RGB顏色模式來設(shè)置該CGContextRef的填充顏色
void CGContextSetRGBFillColor(CGContextRef__nullable c, CGFloat red,
    CGFloat green, CGFloat blue, CGFloat alpha)

//設(shè)置畫筆顏色
void CGContextSetRGBStrokeColor(CGContextRef__nullable c,
    CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)

//使用CMYK顏色模式來設(shè)置該CGContextRef的填充顏色
void CGContextSetCMYKFillColor(CGContextRef__nullable c,
    CGFloat cyan, CGFloat magenta, CGFloat yellow, CGFloat black, CGFloat alpha)

//使用CMYK顏色模式來設(shè)置該CGContextRef的線條顏色
void CGContextSetCMYKStrokeColor(CGContextRef__nullable c,
    CGFloat cyan, CGFloat magenta, CGFloat yellow, CGFloat black, CGFloat alpha)

//在當(dāng)前圖形狀態(tài)設(shè)置渲染意向
void CGContextSetRenderingIntent(CGContextRef__nullable c,
    CGColorRenderingIntent intent)

圖片
UIKit是坐標(biāo)系是y軸向下的; Core Graphics(Quartz)一個(gè)基于2D的圖形繪制引擎厂置,它的坐標(biāo)系則是y軸向上的菩掏;而OpenGL ES是iPhone SDK的2D和3D繪制引擎,它使用左手坐標(biāo)系昵济,它的坐標(biāo)系也是y軸向上的智绸,如果不考慮z軸,在二維下它的坐標(biāo)系和Quartz是一樣的访忿。
所以圖像繪制后會(huì)倒立過來瞧栗,我們可以修改坐標(biāo)系來處理;或者使用UIImage的drawInRect函數(shù)海铆,該函數(shù)內(nèi)部能自動(dòng)處理圖片的正確方向迹恐。

//繪制圖像到圖形上下文中
void CGContextDrawImage(CGContextRef__nullable c, CGRect rect,
    CGImageRef __nullable image)

//重復(fù)繪制的圖像,擴(kuò)展到提供的矩形卧斟,填補(bǔ)當(dāng)前剪輯區(qū)域
void CGContextDrawTiledImage(CGContextRef__nullable c, CGRect rect,
    CGImageRef __nullable image)

//獲取當(dāng)前CGContextRef在放大圖片時(shí)的插值質(zhì)量
CGInterpolationQuality CGContextGetInterpolationQuality(CGContextRef__nullable c)

//設(shè)置圖形上下文的插值質(zhì)量水平
void CGContextSetInterpolationQuality(CGContextRef__nullable c,
    CGInterpolationQuality quality)

注意:因?yàn)閁IKit和CG坐標(biāo)系y軸相反殴边,所以圖片繪制將會(huì)上下顛倒通熄。

1.可以通過修改當(dāng)前坐標(biāo)系來恢復(fù)。
CGContextTranslateCTM(context, 0, height);  
CGContextScaleCTM(context, 1.0, -1.0); 

2.使用UIImage的drawInRect函數(shù)找都,該函數(shù)內(nèi)部能自動(dòng)處理圖片的正確方向
UIGraphicsPushContext(context);  
[image drawInRect:CGRectMake(0, 0, width, height)];  
UIGraphicsPopContext();  

陰影

//設(shè)置陰影在X、Y方向上的偏移廊酣,以及模糊度和陰影的顏色
void CGContextSetShadowWithColor(CGContextRef__nullable c,
    CGSize offset, CGFloat blur, CGColorRef __nullable color)

//設(shè)置陰影在X能耻、Y方向上的偏移,以及模糊度(blur值越大亡驰,陰影越模糊)晓猛。該函數(shù)沒有設(shè)置陰影顏色,默認(rèn)使用1/3透明的黑色(即RGBA{0, 0, 0, 1.0/3.0})作為陰影顏色
void CGContextSetShadow(CGContextRef__nullable c, CGSize offset,
    CGFloat blur)

漸變

//繪制一個(gè)漸變填充定義的出發(fā)點(diǎn)和落腳點(diǎn)沿線變化
void CGContextDrawLinearGradient(CGContextRef__nullable c,
    CGGradientRef __nullable gradient, CGPoint startPoint, CGPoint endPoint,
    CGGradientDrawingOptions options)

//繪制一個(gè)沿著由所提供的開始和結(jié)束的圓限定的區(qū)域變化的漸變填充
void CGContextDrawRadialGradient(CGContextRef__nullable c,
    CGGradientRef __nullable gradient, CGPoint startCenter, CGFloat startRadius,
    CGPoint endCenter, CGFloat endRadius, CGGradientDrawingOptions options)

//使用指定的陰影的背景凡辱,填充剪切路徑
void CGContextDrawShading(CGContextRef __nullable c,
    __nullable CGShadingRef shading)


    //示例
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    NSArray *colors = @[(__bridge id)UIColor.redColor.CGColor,
                        (__bridge id)UIColor.yellowColor.CGColor];
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace,(__bridge CFArrayRef)colors, NULL);
    
    CGPoint startPoint = CGPointMake(0, rect.size.height / 2);
    CGPoint endPoint = CGPointMake(rect.size.width, startPoint.y);
    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation);
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorSpace);

文本

//設(shè)置當(dāng)前字符間距
void CGContextSetCharacterSpacing(CGContextRef__nullable c,
    CGFloat spacing)

//設(shè)置要繪制文本的位置
void CGContextSetTextPosition(CGContextRef__nullable c,
    CGFloat x, CGFloat y)

//返回在繪制文本的位置
CGPoint CGContextGetTextPosition(CGContextRef __nullable c)

//設(shè)置當(dāng)前文本矩陣
void CGContextSetTextMatrix(CGContextRef__nullable c,
    CGAffineTransform t)

//返回當(dāng)前文本矩陣
CGAffineTransform CGContextGetTextMatrix(CGContextRef__nullable c)

//設(shè)置當(dāng)前文本的繪圖模式
void CGContextSetTextDrawingMode(CGContextRef__nullable c,
    CGTextDrawingMode mode)

//設(shè)置上下文的字體
void CGContextSetFont(CGContextRef__nullable c,
    CGFontRef __nullable font)

//設(shè)置上下文的字體大小
void CGContextSetFontSize(CGContextRef__nullable c, CGFloat size)

//在所提供的位置繪制字形
void CGContextShowGlyphsAtPositions(CGContextRef__nullable c,
    const CGGlyph * __nullable glyphs, const CGPoint * __nullable Lpositions,
    size_t count)

PDF

//繪制一個(gè)PDF頁(yè)面到當(dāng)前的用戶空間
void CGContextDrawPDFPage(CGContextRef__nullable c,
    CGPDFPageRef __nullable page)

輸出頁(yè)面

//基于頁(yè)面的圖形上下文中開始了新的一頁(yè)
void CGContextBeginPage(CGContextRef__nullable c,const CGRect *__nullable mediaBox)

//在基于頁(yè)面的圖形上下文結(jié)束當(dāng)前的頁(yè)面
void CGContextEndPage(CGContextRef__nullable c)

上下文相關(guān)方法

//圖形上下文的引用計(jì)數(shù)+1 
(CGContextRef __nullable)CGContextRetain(CGContextRef__nullable c)

//圖形上下文的引用計(jì)數(shù)-1
void CGContextRelease(CGContextRef__nullable c)

//強(qiáng)制所有掛起的繪圖操作在一個(gè)窗口上下文中立即被渲染到目標(biāo)設(shè)備 
void CGContextFlush(CGContextRef__nullable c)

//將一個(gè)窗口的圖像上下文內(nèi)容更新戒职,即所有的繪圖操作都會(huì)在下次同步到窗口上
void CGContextSynchronize(CGContextRef__nullable c)

抗鋸齒

//設(shè)置該CGContextRef是否應(yīng)該抗鋸齒(即光滑圖形曲線邊緣,讓字體渲染比較清晰 提高畫質(zhì)以使之柔和 )
void CGContextSetShouldAntialias(CGContextRef__nullable c,
    bool shouldAntialias)

//設(shè)置該CGContextRef是否允許抗鋸齒
void CGContextSetAllowsAntialiasing(CGContextRef__nullable c,
    bool allowsAntialiasing)

字體展示

//設(shè)置該CGContextRef是否允許光滑字體
void CGContextSetShouldSmoothFonts(CGContextRef__nullable c,
    bool shouldSmoothFonts)

//設(shè)置該CGContextRef是否允許光滑字體
void CGContextSetAllowsFontSmoothing(CGContextRef__nullable c,
    bool allowsFontSmoothing)

//啟用或禁用圖形上下文中的子像素定位透乾。
void CGContextSetShouldSubpixelPositionFonts(
    CGContextRef __nullable c, bool shouldSubpixelPositionFonts)

//設(shè)置是否允許圖形上下文的子像素定位
void CGContextSetAllowsFontSubpixelPositioning(
    CGContextRef __nullable c, bool allowsFontSubpixelPositioning)

//在圖形上下文中啟用或禁用子像素量化洪燥。
void CGContextSetShouldSubpixelQuantizeFonts(
    CGContextRef __nullable c, bool shouldSubpixelQuantizeFonts)

//設(shè)置是否允許圖形上下文的子像素量化
void CGContextSetAllowsFontSubpixelQuantization(
    CGContextRef __nullable c, bool allowsFontSubpixelQuantization)

透明層

/* 開始一個(gè)透明層。
 直到相應(yīng)的調(diào)用CGContextEndTransparencyLayer乳乌,在指定范圍內(nèi)的所有后續(xù)繪制操作組合到一個(gè)完全透明的背景(它被視為一個(gè)單獨(dú)的目標(biāo)緩沖區(qū)從上下文)捧韵。

在透明層中繪制需要三步:
 1.  調(diào)用函數(shù) CGContextBeginTransparencyLayer
 2.  在透明層中繪制需要組合的對(duì)象
 3.  調(diào)用函數(shù) CGContextEndTransparencyLayer*/
void CGContextBeginTransparencyLayer(CGContextRef__nullable c,
    CFDictionaryRef __nullable auxiliaryInfo)

//開始透明度層,它的邊界是指定的矩形汉操,其內(nèi)容是有界的
void CGContextBeginTransparencyLayerWithRect(
    CGContextRef __nullable c, CGRect rect, CFDictionaryRef__nullable auxInfo)

//結(jié)束一個(gè)透明層
void CGContextEndTransparencyLayer(CGContextRef__nullable c)

用戶空間對(duì)設(shè)備空間的變化

/*  獲取Quartz轉(zhuǎn)換用戶空間和設(shè)備空間的仿射變換 */
CGAffineTransform CGContextGetUserSpaceToDeviceSpaceTransform(CGContextRef__nullable c)

/*———— 點(diǎn) ————*/
/* 將一個(gè)CGPoint數(shù)據(jù)結(jié)構(gòu)從一個(gè)空間變換到另一個(gè)空間(DeviceSpace). */
CGPoint CGContextConvertPointToDeviceSpace(CGContextRef__nullable c,
    CGPoint point)

/* 將一個(gè)CGPoint數(shù)據(jù)結(jié)構(gòu)從一個(gè)空間變換到另一個(gè)空間(UserSpace). */
CGPoint CGContextConvertPointToUserSpace(CGContextRef__nullable c,
    CGPoint point)

/*———— 大小 ————*/
/* 將一個(gè)CGSize數(shù)據(jù)結(jié)構(gòu)從一個(gè)空間變換到另一個(gè)空間(DeviceSpace). */
CGSize CGContextConvertSizeToDeviceSpace(CGContextRef__nullable c, CGSize size)

/* 將一個(gè)CGSize數(shù)據(jù)結(jié)構(gòu)從一個(gè)空間變換到另一個(gè)空間(UserSpace). */
CGSize CGContextConvertSizeToUserSpace(CGContextRef__nullable c, CGSize size)

/*———— 矩形 ————*/
/* 將一個(gè)CGPoint數(shù)據(jù)結(jié)構(gòu)從一個(gè)空間變換到另一個(gè)空間(DeviceSpace)再来。 */

CGRect CGContextConvertRectToDeviceSpace(CGContextRef__nullable c,
    CGRect rect)

/* 將一個(gè)CGPoint數(shù)據(jù)結(jié)構(gòu)從一個(gè)空間變換到另一個(gè)空間(UserSpace)。 */
CGRect CGContextConvertRectToUserSpace(CGContextRef__nullable c,
    CGRect rect)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末磷瘤,一起剝皮案震驚了整個(gè)濱河市芒篷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌采缚,老刑警劉巖针炉,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異仰担,居然都是意外死亡糊识,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門摔蓝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赂苗,“玉大人,你說我怎么就攤上這事贮尉“枳蹋” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵猜谚,是天一觀的道長(zhǎng)败砂。 經(jīng)常有香客問我赌渣,道長(zhǎng),這世上最難降的妖魔是什么昌犹? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任坚芜,我火速辦了婚禮,結(jié)果婚禮上斜姥,老公的妹妹穿的比我還像新娘鸿竖。我一直安慰自己,他們只是感情好铸敏,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布缚忧。 她就那樣靜靜地躺著,像睡著了一般杈笔。 火紅的嫁衣襯著肌膚如雪闪水。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天蒙具,我揣著相機(jī)與錄音球榆,去河邊找鬼。 笑死店量,一個(gè)胖子當(dāng)著我的面吹牛芜果,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播融师,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼右钾,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了旱爆?” 一聲冷哼從身側(cè)響起舀射,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎怀伦,沒想到半個(gè)月后脆烟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡房待,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年邢羔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桑孩。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拜鹤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出流椒,到底是詐尸還是另有隱情敏簿,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站惯裕,受9級(jí)特大地震影響温数,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜻势,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一撑刺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧握玛,春花似錦猜煮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)淑蔚。三九已至市殷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刹衫,已是汗流浹背醋寝。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留带迟,地道東北人音羞。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像仓犬,于是被迫代替她去往敵國(guó)和親嗅绰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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