亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS開發中使用Quartz2D繪制上下文棧和矩陣的方法

2020-07-26 03:31:40
字體:
來源:轉載
供稿:網友

上下文棧

一、qurza2d是怎么將繪圖信息和繪圖的屬性繪制到圖形上下文中去的?

說明:

新建一個項目,自定義一個view類和storyboard關聯后,重寫該類中的drowrect方法。
畫線的三個步驟:
(1)獲取上下文
(2)繪圖
(3)渲染
要求:畫兩條單獨的線
代碼和效果圖:

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //繪圖
    //第一條線
    CGContextMoveToPoint(ctx, 20, 100);
    CGContextAddLineToPoint(ctx, 100, 320);
   
    //第二條線
    CGContextMoveToPoint(ctx, 40, 200);
    CGContextAddLineToPoint(ctx, 80, 100);
    //渲染
    CGContextStrokePath(ctx);
   
}


效果圖:

2015112593350541.png (640×960)

設置線段的寬度:兩頭為圓形,顏色等。
代碼和效果圖(發現第二條線也被渲染成第一條線的樣式和狀態)

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //繪圖
    //第一條線
    CGContextMoveToPoint(ctx, 20, 100);
    CGContextAddLineToPoint(ctx, 100, 320);
   
    //設置第一條線的狀態
    //設置線條的寬度
    CGContextSetLineWidth(ctx, 12);
    //設置線條的顏色
    [[UIColor brownColor]set];
    //設置線條兩端的樣式為圓角
    CGContextSetLineCap(ctx,kCGLineCapRound);
    //對線條進行渲染
    CGContextStrokePath(ctx);
   
    //第二條線
    CGContextMoveToPoint(ctx, 40, 200);
    CGContextAddLineToPoint(ctx, 80, 100);
    //渲染
    CGContextStrokePath(ctx);
   
}


效果圖:

2015112593753732.png (640×960)

新的需求:要讓兩條線的顏色不一樣,要求第二條線變成原版的樣子。要達到上面的要求,有以下幾種做法:

第一種做法:
在對第二條線進行設置的時候,清空它的狀態

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //繪圖
    //第一條線
    CGContextMoveToPoint(ctx, 20, 100);
    CGContextAddLineToPoint(ctx, 100, 320);
   
    //設置第一條線的狀態
    //設置線條的寬度
    CGContextSetLineWidth(ctx, 12);
    //設置線條的顏色
    [[UIColor brownColor]set];
    //設置線條兩端的樣式為圓角
    CGContextSetLineCap(ctx,kCGLineCapRound);
    //對線條進行渲染
    CGContextStrokePath(ctx);
   
    //第二條線
    CGContextMoveToPoint(ctx, 40, 200);
    CGContextAddLineToPoint(ctx, 80, 100);
   
    //清空狀態
    CGContextSetLineWidth(ctx, 1);
    [[UIColor blackColor]set];
    CGContextSetLineCap(ctx,kCGLineCapButt);
   
    //渲染
    CGContextStrokePath(ctx);
   
}


第二種做法:
把第一條線從開始繪制到渲染的代碼剪切到第二條線渲染完成之后,這樣先繪制并渲染了第一條線,該線并沒有對繪制信息進行過設置,顯示出來的第二條線即位系統默認的效果。

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //繪圖
   
    //第二條線
    CGContextMoveToPoint(ctx, 40, 200);
    CGContextAddLineToPoint(ctx, 80, 100);
   
    //清空狀態
    //    CGContextSetLineWidth(ctx, 1);
    //    [[UIColor blackColor]set];
   
    //    CGContextSetLineCap(ctx,kCGLineCapButt);
   
    //渲染
    CGContextStrokePath(ctx);
   
    //第一條線
    CGContextMoveToPoint(ctx, 20, 100);
    CGContextAddLineToPoint(ctx, 100, 320);
   
    //設置第一條線的狀態
    //設置線條的寬度
    CGContextSetLineWidth(ctx, 12);
    //設置線條的顏色
    [[UIColor brownColor]set];
    //設置線條兩端的樣式為圓角
    CGContextSetLineCap(ctx,kCGLineCapRound);
    //對線條進行渲染
    CGContextStrokePath(ctx);
}


兩種方式完成的效果相同:

2015112593857750.png (640×960)

但是有的情況下,必須要先畫第一條線再畫第二條線,要求在交叉部分,第二條線蓋在第一條線的上面。如果要求是這樣,那么只能使用第一種做法,但是如果現在有新的需求,要求在這個基礎上再畫兩條線,那就需要清空ctx中的狀態很多次,很麻煩。為了解決這個問題,下面給大家介紹圖形上下文棧。
 
二、繪圖的完整過程
程序啟動,顯示自定義的view。當程序第一次顯示在我們眼前的時候,程序會調用drawRect:方法,在里面獲取了圖形上下文(在內存中擁有了),然后利用圖形上下文保存繪圖信息,可以理解為圖形上下文中有一塊區域用來保存繪圖信息,有一塊區域用來保存繪圖的狀態(線寬,圓角,顏色)。直線不是直接繪制到view上的,可以理解為在圖形上下文中有一塊單獨的區域用來先繪制圖形,當調用渲染方法的時候,再把繪制好的圖形顯示到view上去。
 
在繪制圖形區域,會去保存繪圖狀態區域中查找對應的狀態信息(線寬,圓角,顏色),然后在繪圖區域把對第一條直線繪制完成。其實在渲染之前,就已經把直線在繪制圖形區域畫好了。
如圖:

2015112593917394.png (398×265)

2015112593934980.png (385×261)

說明:這些示意圖和本文中的程序代碼塊,不具備一一對應關系,只是為了說明繪圖的完整過程。
調用渲染方法的時候,把繪制圖形區域已經畫好的圖形直接顯示到view上,就是我們看到的樣子了。
如圖:

2015112594009483.png (407×279)

2015112594027375.png (394×278)

畫第二條的時候,如果沒有對繪圖狀態進行重新設置,那么可以發現畫第一天線的時候使用的繪圖狀態還保存在圖形上下文中,在第二條線進行渲染之前,會根據第一條線(上一份繪圖狀態)對第二條線進行相應的設置,渲染后把第二條線顯示到屏幕上。
參考代碼:

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //繪圖
    //第一條線
    CGContextMoveToPoint(ctx, 20, 100);
    CGContextAddLineToPoint(ctx, 100, 320);
   
    //設置第一條線的狀態
    //設置線條的寬度
    CGContextSetLineWidth(ctx, 12);
    //設置線條的顏色
    [[UIColor brownColor]set];
    //設置線條兩端的樣式為圓角
    CGContextSetLineCap(ctx,kCGLineCapRound);
    //對線條進行渲染
    CGContextStrokePath(ctx);
   
    //第二條線
    CGContextMoveToPoint(ctx, 40, 200);
    CGContextAddLineToPoint(ctx, 80, 100);
    //渲染
    CGContextStrokePath(ctx);
}


如果清空了狀態,則在渲染之前,在繪制圖形區域對第二條線進行繪制的時候,會去查找當前的繪圖信息(已經更改――清空),根據繪圖信息對第二條線進行繪制,調用渲染方法的時候把第二條線顯示到view上。
參考代碼:

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //繪圖
    //第一條線
    CGContextMoveToPoint(ctx, 20, 100);
    CGContextAddLineToPoint(ctx, 100, 320);
   
    //設置第一條線的狀態
    //設置線條的寬度
    CGContextSetLineWidth(ctx, 12);
    //設置線條的顏色
    [[UIColor brownColor]set];
    //設置線條兩端的樣式為圓角
    CGContextSetLineCap(ctx,kCGLineCapRound);
    //對線條進行渲染
    CGContextStrokePath(ctx);
   
    //第二條線
    CGContextMoveToPoint(ctx, 40, 200);
    CGContextAddLineToPoint(ctx, 80, 100);
   
    //清空狀態
    CGContextSetLineWidth(ctx, 1);
    [[UIColor blackColor]set];
    CGContextSetLineCap(ctx,kCGLineCapButt);
   
    //渲染
    CGContextStrokePath(ctx);
}

三、圖形上下文棧
1.簡單說明
在獲取圖形上下文之后,通過 CGContextSaveGState(ctx); 方法,把當前獲取的上下文拷貝一份,保存一份最純潔的圖形上下文。
在畫第二條線之前,使用CGContextRestoreGState(ctx);方法,還原開始的時候保存的那份最純潔的圖形上下文。
代碼:

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //保存一份最初的圖形上下文
    CGContextSaveGState(ctx);
   
    //繪圖
    //第一條線
    CGContextMoveToPoint(ctx, 20, 100);
    CGContextAddLineToPoint(ctx, 100, 320);
   
    //設置第一條線的狀態
    //設置線條的寬度
    CGContextSetLineWidth(ctx, 12);
    //設置線條的顏色
    [[UIColor brownColor]set];
    //設置線條兩端的樣式為圓角
    CGContextSetLineCap(ctx,kCGLineCapRound);
    //對線條進行渲染
    CGContextStrokePath(ctx);
   
    //還原開始的時候保存的那份最純潔的圖形上下文
    CGContextRestoreGState(ctx);
    //第二條線
    CGContextMoveToPoint(ctx, 40, 200);
    CGContextAddLineToPoint(ctx, 80, 100);
   
    //清空狀態
//    CGContextSetLineWidth(ctx, 1);
//    [[UIColor blackColor]set];
//    CGContextSetLineCap(ctx,kCGLineCapButt);
   
    //渲染
    CGContextStrokePath(ctx);
}

2.圖形上下文棧機制
畫第一條線的時候,會把當前的圖形上下文拷貝一份保存到圖形上下文棧中。
2015112594145463.png (489×302)

畫第二條線的時候,去圖形上下文棧中取出棧頂的繪圖信息,作為第二條線的狀態信息,第二條線的狀態信息也是據此(最初保存的那份圖形上下文)進行繪制。

2015112594206293.png (507×256)

2015112594224477.png (505×301)

注意:在棧里保存了幾次,那么就可以取幾次(比如不能保存了1次,取兩次,在取第二次的時候,棧里為空會直接掛掉)。

矩陣操作
一、關于矩陣操作
1.畫一個四邊形
通過設置兩個端點(長和寬)來完成一個四邊形的繪制。
代碼:

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //畫四邊形
    //獲取圖形上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //繪圖
    CGContextAddRect(ctx, CGRectMake(20, 50, 100, 100));
    //渲染
    CGContextStrokePath(ctx);
}


說明:通過這種方式畫矩形有弱點:畫出來的矩形永遠都是正的。如下圖:

2015112594300570.png (640×960)

2.畫一個歪的四邊形
如何畫一個歪的矩形?(通過矩陣操作來完成,和形變操作相似)
可以通過矩陣操作,把畫出來的東西進行形變(旋轉,縮放,平移)
方法:CGContextRotateCTM(<#CGContextRef c#>, <#CGFloat angle#>)該接受兩個參數(圖形上下文,弧度)
注意點:設置矩陣操作必須要在添加圖形之前,如果設置在添加圖形之后的話,此時它已經畫完了,無效。
代碼:

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //畫四邊形
    //獲取圖形上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //矩陣操作
    //注意點:設置矩陣操作必須要在添加繪圖信息之前
    //旋轉45度
    CGContextRotateCTM(ctx, M_PI_4);
   
    //繪圖
    CGContextAddRect(ctx, CGRectMake(150, 100, 100, 100));
    //渲染
    CGContextStrokePath(ctx);
}


效果:

2015112594321021.png (640×960)

二、關于旋轉
1.旋轉演示
view之所以能夠顯示視圖,是因為它的上面有layer,將來圖形也是渲染到layer上面。
且,旋轉的時候是整個layer都旋轉了,可以再畫一個圓進行驗證。
代碼1(未旋轉):

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取圖形上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //矩陣操作
    //注意點:設置矩陣操作必須要在添加繪圖信息之前
    //旋轉45度
    //    CGContextRotateCTM(ctx, M_PI_4);
   
    //繪圖
    //畫四邊形
    CGContextAddRect(ctx, CGRectMake(150, 100, 100, 100));
    //畫一個圓
    CGContextAddEllipseInRect(ctx, CGRectMake(200, 200, 50, 50));
    //渲染
    CGContextStrokePath(ctx);
}


 效果:

2015112594339184.png (640×960)

代碼2(旋轉):

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取圖形上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //矩陣操作
    //注意點:設置矩陣操作必須要在添加繪圖信息之前
    //旋轉45度
    CGContextRotateCTM(ctx, M_PI_4);
   
    //繪圖
    //畫四邊形
    CGContextAddRect(ctx, CGRectMake(150, 100, 100, 100));
    //畫一個圓
    CGContextAddEllipseInRect(ctx, CGRectMake(200, 200, 50, 50));
    //渲染
    CGContextStrokePath(ctx);
}


效果:

2015112594402270.png (640×960)

2.關于旋轉的補充說明
提示:旋轉的時候,是整個layer都旋轉了。

2015112594420729.png (360×212)

三、縮放
方法:CGContextScaleCTM(<#CGContextRef c#>, <#CGFloat sx#>, <#CGFloat sy#>)
該方法接收三個參數(圖形上下文,x方向的縮放比例,y方向上的縮放比例
代碼示例:

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取圖形上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //矩陣操作
    //注意點:設置矩陣操作必須要在添加繪圖信息之前
    //縮放,x方向縮放0.5倍,y方向縮放1.5倍
    CGContextScaleCTM(ctx, 0.5, 1.5);
   
    //繪圖
    //畫四邊形
    CGContextAddRect(ctx, CGRectMake(150, 100, 100, 100));
    //畫一個圓
    CGContextAddEllipseInRect(ctx, CGRectMake(200, 200, 50, 50));
    //渲染
    CGContextStrokePath(ctx);
}


效果:

2015112594448453.png (640×960)

四、平移
方法: CGContextTranslateCTM(<#CGContextRef c#>, <#CGFloat tx#>, <#CGFloat ty#>)
該方法接收三個參數(圖形上下文,x方向的偏移量,y方向上的偏移量)  
代碼示例:

復制代碼 代碼如下:

- (void)drawRect:(CGRect)rect
{
    //獲取圖形上下文
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    //矩陣操作
    //注意點:設置矩陣操作必須要在添加繪圖信息之前
    //平移,x方向移動50,y方向移動100
    CGContextTranslateCTM(ctx, 50, 100);
   
    //繪圖
    //畫四邊形
    CGContextAddRect(ctx, CGRectMake(150, 100, 100, 100));
    //畫一個圓
    CGContextAddEllipseInRect(ctx, CGRectMake(200, 200, 50, 50));
    //渲染
    CGContextStrokePath(ctx);
}


效果:

2015112594513990.png (640×960)

提示:坐標原點為view的左上角。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品美女主播在线观看纯欲| 亚洲剧情一区二区| 国产精品成久久久久三级| 国产日韩欧美日韩| 久久国产精品网站| 亚洲一区美女视频在线观看免费| 亚洲字幕在线观看| 91九色精品视频| 国产日韩换脸av一区在线观看| 日韩在线观看免费高清完整版| 国产精品免费一区| 国产精品久久久久久久久久久久| 日韩美女av在线免费观看| 欧美在线激情网| 亚洲欧美制服第一页| 日韩最新免费不卡| 久久九九有精品国产23| 国产精品成人av在线| 性欧美xxxx视频在线观看| 国产精品偷伦视频免费观看国产| 亚洲a区在线视频| 狠狠躁夜夜躁人人爽超碰91| 亚洲欧美日韩直播| 全色精品综合影院| 欧美福利视频网站| 亚洲va欧美va国产综合久久| 亚州欧美日韩中文视频| 91视频国产精品| 97国产一区二区精品久久呦| 亚洲欧美一区二区三区情侣bbw| 成人性生交大片免费看视频直播| 欧美高清视频在线播放| 在线视频欧美日韩精品| 7m精品福利视频导航| 在线成人免费网站| 91在线高清视频| 久久精品久久久久久国产 免费| 久久久久久国产| 日韩欧美成人免费视频| 久久精品久久久久电影| 欧美日韩国产一区二区| 国产精品偷伦视频免费观看国产| 久久久伊人日本| 亚洲福利精品在线| 亚洲一区亚洲二区亚洲三区| 亚洲精品电影网站| 国产欧美久久久久久| 欧美国产日韩一区二区| 欧美刺激性大交免费视频| 欧美色videos| 欧美日韩中文字幕在线视频| 欧美一级黑人aaaaaaa做受| 91亚洲精品一区| 日韩中文字幕在线免费观看| 91视频-88av| 欧美精品在线网站| 亚洲欧美中文字幕在线一区| 78m国产成人精品视频| 久久国产精品久久国产精品| 日韩欧美国产高清91| 亚洲免费伊人电影在线观看av| 国产精品久久久久久久久免费| 色综合导航网站| 国产精品成人免费电影| 在线观看视频99| 2018国产精品视频| 欧美成年人在线观看| 欧美日韩成人在线视频| 人九九综合九九宗合| 国产日韩精品入口| 性欧美在线看片a免费观看| 在线成人一区二区| 欧美日韩午夜视频在线观看| 中文字幕在线看视频国产欧美| 日韩av电影中文字幕| 97精品一区二区三区| 久久综合久中文字幕青草| 欧美国产日韩在线| 亚洲欧洲中文天堂| 成人黄色短视频在线观看| 国产精品女主播| 欧美美女操人视频| 日韩中文字幕网站| 欧美影院久久久| 国产香蕉一区二区三区在线视频| 欧美精品www| 欧美黑人一区二区三区| 一区二区三区天堂av| 日韩69视频在线观看| 亚洲精品99久久久久中文字幕| 日韩欧美在线免费观看| 亚洲精品视频二区| 国产精品扒开腿做爽爽爽视频| 欧美在线播放视频| 欧美大肥婆大肥bbbbb| 日韩在线欧美在线国产在线| 精品国产欧美一区二区三区成人| 亚洲精品国产精品国自产在线| 亚洲区一区二区| 成人激情视频在线| 日韩免费看的电影电视剧大全| 欧美高清视频在线| 亚洲国产成人精品久久久国产成人一区| 奇门遁甲1982国语版免费观看高清| 日韩欧美综合在线视频| 人人爽久久涩噜噜噜网站| 久久久电影免费观看完整版| 欧美精品免费看| 国产精品美女无圣光视频| 欧美国产第一页| 欧美性猛交xxxx黑人| 日韩精品在线观看网站| 亚洲成人久久电影| 国产精品成人av在线| 97视频在线观看亚洲| 国产成人高清激情视频在线观看| 久久精品亚洲94久久精品| 日韩电影免费在线观看中文字幕| 欧美大片在线看免费观看| 欧美日韩成人在线观看| 欧美性高潮床叫视频| 日韩网站免费观看高清| 欧美一区二区三区四区在线| 国产精品老女人精品视频| 国产婷婷97碰碰久久人人蜜臀| 国产精品旅馆在线| 欧美亚州一区二区三区| 日韩在线视频导航| 国产精品视频永久免费播放| 亚洲高清色综合| 国产欧美精品久久久| 国产精品视频大全| 国产精品欧美日韩一区二区| 中文字幕无线精品亚洲乱码一区| 91精品国产色综合久久不卡98口| 国产精品日韩av| 国产精品视频导航| 国产成人在线播放| 国产精品久久av| 久久影院在线观看| 亚洲有声小说3d| 欧美一级淫片丝袜脚交| 欧美乱大交xxxxx| 欧美午夜www高清视频| 亚洲成人1234| 欧美午夜女人视频在线| 亚洲欧美日韩国产中文专区| 国产亚洲欧洲黄色| 欧美人与性动交a欧美精品| 97在线视频国产| 国产做受69高潮| 亚洲国产精品女人久久久| 在线免费看av不卡| 欧美精品电影在线| 91国产美女视频| 欧美激情小视频| 日韩中文在线观看| 国产精品自拍偷拍| 亚洲国产日韩一区| 国精产品一区一区三区有限在线| 91免费看片网站| 欧美色图在线视频| 亚洲国产精品字幕| 国产一区二区丝袜高跟鞋图片|