?1 - (void)drawRect:(CGRect)rect 2 { 3 //獲取上下文 4 CGContextRef ctx=UIGraphicsGetCurrentContext(); 5 //繪圖 6 //第一條線 7 CGContextMoveToPoint(ctx, 20, 100); 8 CGContextAddLineToPoint(ctx, 100, 320); 9 10 //設(shè)置第一條線的狀態(tài) 11 //設(shè)置線條的寬度 12 CGContextSetLineWidth(ctx, 12); 13 //設(shè)置線條的顏色 14 [[UIColor brownColor]set]; 15 //設(shè)置線條兩端的樣式為圓角 16 CGContextSetLineCap(ctx,kCGLineCapRound); 17 //對(duì)線條進(jìn)行渲染 18 CGContextStrokePath(ctx); 19 20 //第二條線 21 CGContextMoveToPoint(ctx, 40, 200); 22 CGContextAddLineToPoint(ctx, 80, 100); 23 //渲染 24 CGContextStrokePath(ctx); 25 26 } 效果圖: 新的需求:要讓兩條線的顏色不一樣,要求第二條線變成原版的樣子。要達(dá)到上面的要求,有以下幾種做法: 第一種做法: 在對(duì)第二條線進(jìn)行設(shè)置的時(shí)候,清空它的狀態(tài) 1 - (void)drawRect:(CGRect)rect 2 { 3 //獲取上下文 4 CGContextRef ctx=UIGraphicsGetCurrentContext(); 5 //繪圖 6 //第一條線 7 CGContextMoveToPoint(ctx, 20, 100); 8 CGContextAddLineToPoint(ctx, 100, 320); 9 10 //設(shè)置第一條線的狀態(tài) 11 //設(shè)置線條的寬度 12 CGContextSetLineWidth(ctx, 12); 13 //設(shè)置線條的顏色 14 [[UIColor brownColor]set]; 15 //設(shè)置線條兩端的樣式為圓角 16 CGContextSetLineCap(ctx,kCGLineCapRound); 17 //對(duì)線條進(jìn)行渲染 18 CGContextStrokePath(ctx); 19 20 //第二條線 21 CGContextMoveToPoint(ctx, 40, 200); 22 CGContextAddLineToPoint(ctx, 80, 100); 23 24 //清空狀態(tài) 25 CGContextSetLineWidth(ctx, 1); 26 [[UIColor blackColor]set]; 27 CGContextSetLineCap(ctx,kCGLineCapButt); 28 29 //渲染 30 CGContextStrokePath(ctx); 31 32 } 第二種做法: 把第一條線從開始繪制到渲染的代碼剪切到第二條線渲染完成之后,這樣先繪制并渲染了第一條線,該線并沒有對(duì)繪制信息進(jìn)行過設(shè)置,顯示出來的第二條線即位系統(tǒng)默認(rèn)的效果。 1 - (void)drawRect:(CGRect)rect 2 { 3 //獲取上下文 4 CGContextRef ctx=UIGraphicsGetCurrentContext(); 5 //繪圖 6 7 //第二條線 8 CGContextMoveToPoint(ctx, 40, 200); 9 CGContextAddLineToPoint(ctx, 80, 100); 10 11 //清空狀態(tài) 12 // CGContextSetLineWidth(ctx, 1); 13 // [[UIColor blackColor]set]; 14 15 // CGContextSetLineCap(ctx,kCGLineCapButt); 16 17 //渲染 18 CGContextStrokePath(ctx); 19 20 //第一條線 21 CGContextMoveToPoint(ctx, 20, 100); 22 CGContextAddLineToPoint(ctx, 100, 320); 23 24 //設(shè)置第一條線的狀態(tài) 25 //設(shè)置線條的寬度 26 CGContextSetLineWidth(ctx, 12); 27 //設(shè)置線條的顏色 28 [[UIColor brownColor]set]; 29 //設(shè)置線條兩端的樣式為圓角 30 CGContextSetLineCap(ctx,kCGLineCapRound); 31 //對(duì)線條進(jìn)行渲染 32 CGContextStrokePath(ctx); 33 } 兩種方式完成的效果相同: 但是有的情況下,必須要先畫第一條線再畫第二條線,要求在交叉部分,第二條線蓋在第一條線的上面。如果要求是這樣,那么只能使用第一種做法,但是如果現(xiàn)在有新的需求,要求在這個(gè)基礎(chǔ)上再畫兩條線,那就需要清空ctx中的狀態(tài)很多次,很麻煩。為了解決這個(gè)問題,下面給大家介紹圖形上下文棧。 二、繪圖的完整過程 程序啟動(dòng),顯示自定義的view。當(dāng)程序第一次顯示在我們眼前的時(shí)候,程序會(huì)調(diào)用drawRect:方法,在里面獲取了圖形上下文(在內(nèi)存中擁有了),然后利用圖形上下文保存繪圖信息,可以理解為圖形上下文中有一塊區(qū)域用來保存繪圖信息,有一塊區(qū)域用來保存繪圖的狀態(tài)(線寬,圓角,顏色)。直線不是直接繪制到view上的,可以理解為在圖形上下文中有一塊單獨(dú)的區(qū)域用來先繪制圖形,當(dāng)調(diào)用渲染方法的時(shí)候,再把繪制好的圖形顯示到view上去。 在繪制圖形區(qū)域,會(huì)去保存繪圖狀態(tài)區(qū)域中查找對(duì)應(yīng)的狀態(tài)信息(線寬,圓角,顏色),然后在繪圖區(qū)域把對(duì)第一條直線繪制完成。其實(shí)在渲染之前,就已經(jīng)把直線在繪制圖形區(qū)域畫好了。 如圖: 說明:這些示意圖和本文中的程序代碼塊,不具備一一對(duì)應(yīng)關(guān)系,只是為了說明繪圖的完整過程。 調(diào)用渲染方法的時(shí)候,把繪制圖形區(qū)域已經(jīng)畫好的圖形直接顯示到view上,就是我們看到的樣子了。 如圖: 畫第二條的時(shí)候,如果沒有對(duì)繪圖狀態(tài)進(jìn)行重新設(shè)置,那么可以發(fā)現(xiàn)畫第一天線的時(shí)候使用的繪圖狀態(tài)還保存在圖形上下文中,在第二條線進(jìn)行渲染之前,會(huì)根據(jù)第一條線(上一份繪圖狀態(tài))對(duì)第二條線進(jìn)行相應(yīng)的設(shè)置,渲染后把第二條線顯示到屏幕上。 參考代碼: 1 - (void)drawRect:(CGRect)rect 2 { 3 //獲取上下文 4 CGContextRef ctx=UIGraphicsGetCurrentContext(); 5 //繪圖 6 //第一條線 7 CGContextMoveToPoint(ctx, 20, 100); 8 CGContextAddLineToPoint(ctx, 100, 320); 9 10 //設(shè)置第一條線的狀態(tài) 11 //設(shè)置線條的寬度 12 CGContextSetLineWidth(ctx, 12); 13 //設(shè)置線條的顏色 14 [[UIColor brownColor]set]; 15 //設(shè)置線條兩端的樣式為圓角 16 CGContextSetLineCap(ctx,kCGLineCapRound); 17 //對(duì)線條進(jìn)行渲染 18 CGContextStrokePath(ctx); 19 20 //第二條線 21 CGContextMoveToPoint(ctx, 40, 200); 22 CGContextAddLineToPoint(ctx, 80, 100); 23 //渲染 24 CGContextStrokePath(ctx); 25 } 如果清空了狀態(tài),則在渲染之前,在繪制圖形區(qū)域?qū)Φ诙l線進(jìn)行繪制的時(shí)候,會(huì)去查找當(dāng)前的繪圖信息(已經(jīng)更改——清空),根據(jù)繪圖信息對(duì)第二條線進(jìn)行繪制,調(diào)用渲染方法的時(shí)候把第二條線顯示到view上。 參考代碼: 1 - (void)drawRect:(CGRect)rect 2 { 3 //獲取上下文 4 CGContextRef ctx=UIGraphicsGetCurrentContext(); 5 //繪圖 6 //第一條線 7 CGContextMoveToPoint(ctx, 20, 100); 8 CGContextAddLineToPoint(ctx, 100, 320); 9 10 //設(shè)置第一條線的狀態(tài) 11 //設(shè)置線條的寬度 12 CGContextSetLineWidth(ctx, 12); 13 //設(shè)置線條的顏色 14 [[UIColor brownColor]set]; 15 //設(shè)置線條兩端的樣式為圓角 16 CGContextSetLineCap(ctx,kCGLineCapRound); 17 //對(duì)線條進(jìn)行渲染 18 CGContextStrokePath(ctx); 19 20 //第二條線 21 CGContextMoveToPoint(ctx, 40, 200); 22 CGContextAddLineToPoint(ctx, 80, 100); 23 24 //清空狀態(tài) 25 CGContextSetLineWidth(ctx, 1); 26 [[UIColor blackColor]set]; 27 CGContextSetLineCap(ctx,kCGLineCapButt); 28 29 //渲染 30 CGContextStrokePath(ctx); 31 } 三、圖形上下文棧 1.簡(jiǎn)單說明 在獲取圖形上下文之后,通過CGContextSaveGState(ctx); 方法,把當(dāng)前獲取的上下文拷貝一份,保存一份最純潔的圖形上下文。在畫第二條線之前,使用CGContextRestoreGState(ctx);方法,還原開始的時(shí)候保存的那份最純潔的圖形上下文。 代碼: 1 - (void)drawRect:(CGRect)rect 2 { 3 //獲取上下文 4 CGContextRef ctx=UIGraphicsGetCurrentContext(); 5 //保存一份最初的圖形上下文 6 CGContextSaveGState(ctx); 7 8 //繪圖 9 //第一條線 10 CGContextMoveToPoint(ctx, 20, 100); 11 CGContextAddLineToPoint(ctx, 100, 320); 12 13 //設(shè)置第一條線的狀態(tài) 14 //設(shè)置線條的寬度 15 CGContextSetLineWidth(ctx, 12); 16 //設(shè)置線條的顏色 17 [[UIColor brownColor]set]; 18 //設(shè)置線條兩端的樣式為圓角 19 CGContextSetLineCap(ctx,kCGLineCapRound); 20 //對(duì)線條進(jìn)行渲染 21 CGContextStrokePath(ctx); 22 23 //還原開始的時(shí)候保存的那份最純潔的圖形上下文 24 CGContextRestoreGState(ctx); 25 //第二條線 26 CGContextMoveToPoint(ctx, 40, 200); 27 CGContextAddLineToPoint(ctx, 80, 100); 28 29 //清空狀態(tài) 30 // CGContextSetLineWidth(ctx, 1); 31 // [[UIColor blackColor]set]; 32 // CGContextSetLineCap(ctx,kCGLineCapButt); 33 34 //渲染 35 CGContextStrokePath(ctx); 36 } 2.圖形上下文棧機(jī)制 畫第一條線的時(shí)候,會(huì)把當(dāng)前的圖形上下文拷貝一份保存到圖形上下文棧中。 畫第二條線的時(shí)候,去圖形上下文棧中取出棧頂?shù)睦L圖信息,作為第二條線的狀態(tài)信息,第二條線的狀態(tài)信息也是據(jù)此(最初保存的那份圖形上下文)進(jìn)行繪制。 注意:在棧里保存了幾次,那么就可以取幾次(比如不能保存了1次,取兩次,在取第二次的時(shí)候,棧里為空會(huì)直接掛掉)。 來源:http://www./content-4-109751.html |
|