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 //設置第一條線的狀態 11 //設置線條的寬度 12 CGContextSetLineWidth(ctx, 12); 13 //設置線條的顏色 14 [[UIColor brownColor]set]; 15 //設置線條兩端的樣式爲圓角 16 CGContextSetLineCap(ctx,kCGLineCapRound); 17 //對線條進行渲染 18 CGContextStrokePath(ctx); 19 20 //第二條線 21 CGContextMoveToPoint(ctx, 40, 200); 22 CGContextAddLineToPoint(ctx, 80, 100); 23 //渲染 24 CGContextStrokePath(ctx); 25 26 }
效果圖:blog
新的需求:要讓兩條線的顏色不同,要求第二條線變成原版的樣子。要達到上面的要求,有如下幾種作法:內存
第一種作法:it
在對第二條線進行設置的時候,清空它的狀態class
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 //設置第一條線的狀態 11 //設置線條的寬度 12 CGContextSetLineWidth(ctx, 12); 13 //設置線條的顏色 14 [[UIColor brownColor]set]; 15 //設置線條兩端的樣式爲圓角 16 CGContextSetLineCap(ctx,kCGLineCapRound); 17 //對線條進行渲染 18 CGContextStrokePath(ctx); 19 20 //第二條線 21 CGContextMoveToPoint(ctx, 40, 200); 22 CGContextAddLineToPoint(ctx, 80, 100); 23 24 //清空狀態 25 CGContextSetLineWidth(ctx, 1); 26 [[UIColor blackColor]set]; 27 CGContextSetLineCap(ctx,kCGLineCapButt); 28 29 //渲染 30 CGContextStrokePath(ctx); 31 32 }
第二種作法:基礎
把第一條線從開始繪製到渲染的代碼剪切到第二條線渲染完成以後,這樣先繪製並渲染了第一條線,該線並無對繪製信息進行過設置,顯示出來的第二條線即位系統默認的效果。渲染
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 //清空狀態 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 //設置第一條線的狀態 25 //設置線條的寬度 26 CGContextSetLineWidth(ctx, 12); 27 //設置線條的顏色 28 [[UIColor brownColor]set]; 29 //設置線條兩端的樣式爲圓角 30 CGContextSetLineCap(ctx,kCGLineCapRound); 31 //對線條進行渲染 32 CGContextStrokePath(ctx); 33 }
兩種方式完成的效果相同:scroll
可是有的狀況下,必需要先畫第一條線再畫第二條線,要求在交叉部分,第二條線蓋在第一條線的上面。若是要求是這樣,那麼只能使用第一種作法,可是若是如今有新的需求,要求在這個基礎上再畫兩條線,那就須要清空ctx中的狀態不少次,很麻煩。爲了解決這個問題,下面給你們介紹圖形上下文棧。程序
2、繪圖的完整過程方法
程序啓動,顯示自定義的view。當程序第一次顯示在咱們眼前的時候,程序會調用drawRect:方法,在裏面獲取了圖形上下文(在內存中擁有了),而後利用圖形上下文保存繪圖信息,能夠理解爲圖形上下文中有一塊區域用來保存繪圖信息,有一塊區域用來保存繪圖的狀態(線寬,圓角,顏色)。直線不是直接繪製到view上的,能夠理解爲在圖形上下文中有一塊單獨的區域用來先繪製圖形,當調用渲染方法的時候,再把繪製好的圖形顯示到view上去。im
在繪製圖形區域,會去保存繪圖狀態區域中查找對應的狀態信息(線寬,圓角,顏色),而後在繪圖區域把對第一條直線繪製完成。其實在渲染以前,就已經把直線在繪製圖形區域畫好了。
如圖:
說明:這些示意圖和本文中的程序代碼塊,不具有一一對應關係,只是爲了說明繪圖的完整過程。
調用渲染方法的時候,把繪製圖形區域已經畫好的圖形直接顯示到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 //設置第一條線的狀態 11 //設置線條的寬度 12 CGContextSetLineWidth(ctx, 12); 13 //設置線條的顏色 14 [[UIColor brownColor]set]; 15 //設置線條兩端的樣式爲圓角 16 CGContextSetLineCap(ctx,kCGLineCapRound); 17 //對線條進行渲染 18 CGContextStrokePath(ctx); 19 20 //第二條線 21 CGContextMoveToPoint(ctx, 40, 200); 22 CGContextAddLineToPoint(ctx, 80, 100); 23 //渲染 24 CGContextStrokePath(ctx); 25 }
若是清空了狀態,則在渲染以前,在繪製圖形區域對第二條線進行繪製的時候,會去查找當前的繪圖信息(已經更改——清空),根據繪圖信息對第二條線進行繪製,調用渲染方法的時候把第二條線顯示到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 //設置第一條線的狀態 11 //設置線條的寬度 12 CGContextSetLineWidth(ctx, 12); 13 //設置線條的顏色 14 [[UIColor brownColor]set]; 15 //設置線條兩端的樣式爲圓角 16 CGContextSetLineCap(ctx,kCGLineCapRound); 17 //對線條進行渲染 18 CGContextStrokePath(ctx); 19 20 //第二條線 21 CGContextMoveToPoint(ctx, 40, 200); 22 CGContextAddLineToPoint(ctx, 80, 100); 23 24 //清空狀態 25 CGContextSetLineWidth(ctx, 1); 26 [[UIColor blackColor]set]; 27 CGContextSetLineCap(ctx,kCGLineCapButt); 28 29 //渲染 30 CGContextStrokePath(ctx); 31 }
3、圖形上下文棧
1.簡單說明
CGContextSaveGState(ctx);
方法,把當前獲取的上下文拷貝一份,保存一份最純潔的圖形上下文。在畫第二條線以前,使用CGContextRestoreGState(ctx);方法,還原開始的時候保存的那份最純潔的圖形上下文。
代碼:
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 //設置第一條線的狀態 14 //設置線條的寬度 15 CGContextSetLineWidth(ctx, 12); 16 //設置線條的顏色 17 [[UIColor brownColor]set]; 18 //設置線條兩端的樣式爲圓角 19 CGContextSetLineCap(ctx,kCGLineCapRound); 20 //對線條進行渲染 21 CGContextStrokePath(ctx); 22 23 //還原開始的時候保存的那份最純潔的圖形上下文 24 CGContextRestoreGState(ctx); 25 //第二條線 26 CGContextMoveToPoint(ctx, 40, 200); 27 CGContextAddLineToPoint(ctx, 80, 100); 28 29 //清空狀態 30 // CGContextSetLineWidth(ctx, 1); 31 // [[UIColor blackColor]set]; 32 // CGContextSetLineCap(ctx,kCGLineCapButt); 33 34 //渲染 35 CGContextStrokePath(ctx); 36 }
2.圖形上下文棧機制
畫第一條線的時候,會把當前的圖形上下文拷貝一份保存到圖形上下文棧中。
畫第二條線的時候,去圖形上下文棧中取出棧頂的繪圖信息,做爲第二條線的狀態信息,第二條線的狀態信息也是據此(最初保存的那份圖形上下文)進行繪製。
注意:在棧裏保存了幾回,那麼就能夠取幾回(好比不能保存了1次,取兩次,在取第二次的時候,棧裏爲空會直接掛掉)。