iOS繪圖—— UIBezierPath 和 Core Graphics

前言

iOS系統(tǒng)本身提供了兩套繪圖的框架邮丰,即UIBezierPathCore Graphics行您。而前者所屬UIKit,其實是對Core Graphics框架關(guān)于path的進一步封裝剪廉,所以使用起來比較簡單娃循。但是畢竟Core Graphics更接近底層,所以它更加強大斗蒋。

UIBezierPath

可以創(chuàng)建基于矢量的路徑捌斧,例如橢圓或者矩形,或者有多個直線和曲線段組成的形狀泉沾。

使用UIBezierPath捞蚂,你只能在當(dāng)前上下文中繪圖,所以如果你當(dāng)前處于UIGraphicsBeginImageContextWithOptions函數(shù)或drawRect:方法中跷究,你就可以直接使用UIKit提供的方法進行繪圖姓迅。如果你持有一個context:參數(shù),那么使用UIKit提供的方法之前,必須將該上下文參數(shù)轉(zhuǎn)化為當(dāng)前上下文丁存。幸運的是肩杈,調(diào)用UIGraphicsPushContext 函數(shù)可以方便的將context:參數(shù)轉(zhuǎn)化為當(dāng)前上下文,記住最后別忘了調(diào)用UIGraphicsPopContext函數(shù)恢復(fù)上下文環(huán)境解寝。

簡言之:我們一般使用UIBezierPath都是在重寫的drawRecrt方法這種情形扩然。其繪圖的步驟是這樣的:

  • 1.重寫drawRect方法队腐。但不需要我們自己獲取當(dāng)前上下文context;
  • 2.創(chuàng)建相應(yīng)圖形的UIBezierPath對象帆卓,并設(shè)置一些修飾屬性见芹;
  • 3.渲染,完成繪制始绍。
- (void)drawRect:(CGRect)rect // 1.重寫drawRect方法
{
    UIBezierPath* aPath = [UIBezierPath bezierPathWithRect:CGRectMake(20, 20, 100, 50)]; // 2.創(chuàng)建圖形相應(yīng)的UIBezierPath對象

    // 3.設(shè)置一些修飾屬性 
    aPath.lineWidth = 8.0;
    aPath.lineCapStyle = kCGLineCapRound; 
    aPath.lineJoinStyle = kCGLineCapRound; 
    UIColor *color = [UIColor colorWithRed:0 green:0 blue:0.7 alpha:1];
    [color set]; 

    [aPath stroke]; // 4.渲染,完成繪制
}

需要理解的東西不多,主要是一些代碼需要記憶抑片。所以就不寫代碼了,直接看別人的代碼:繪圖1-UIBezierPath


Core Graphics

這是一個繪圖專用的API族杨赤,它經(jīng)常被稱為QuartZ或QuartZ 2D敞斋。Core Graphics是iOS上所有繪圖功能的基石,包括UIKit疾牲。

要搞清楚Core Graphics就要搞清楚下面幾個問題:

** 1.繪圖需要 CGContextRef**
CGContextRef即圖形上下文植捎。可以這么理解阳柔,我們繪圖是需要一個載體或者說輸出目標(biāo)焰枢,它用來顯示繪圖信息,并且決定繪制的東西輸出到哪個地方舌剂〖贸可以形象的比喻context就像一個“畫板”,我們得把圖形繪制到這個畫板上霍转。所以荐绝,繪圖必須要先有context。
** 2.怎么拿到context避消?**

第一種方法是利用cocoa為你生成的圖形上下文低滩。當(dāng)你子類化了一個UIView并實現(xiàn)了自己的drawRect:方法后,一旦drawRect:方法被調(diào)用岩喷,Cocoa就會為你創(chuàng)建一個圖形上下文委造,此時你對圖形上下文的所有繪圖操作都會顯示在UIView上。

第二種方法就是創(chuàng)建一個圖片類型的上下文均驶。調(diào)用UIGraphicsBeginImageContextWithOptions函數(shù)就可獲得用來處理圖片的圖形上下文昏兆。利用該上下文,你就可以在其上進行繪圖,并生成圖片爬虱。調(diào)用UIGraphicsGetImageFromCurrentImageContext函數(shù)可從當(dāng)前上下文中獲取一個UIImage對象隶债。記住在你所有的繪圖操作后別忘了調(diào)用UIGraphicsEndImageContext函數(shù)關(guān)閉圖形上下文。

簡言之:

  • 重寫UIView的drawRect方法跑筝,在該方法里便可得到context死讹;
  • 調(diào)用UIGraphicsBeginImageContextWithOptions方法得到context;

** 3.注意**
并不是說一提到繪圖曲梗,就一定得重寫drawRect方法赞警,只是因為通常情況下我們一般采用在drawRect方法里獲取context這種方式。

** 4.drawRect方法什么時候觸發(fā)**

  • 1.當(dāng)view第一次顯示到屏幕上時虏两;
  • 2.當(dāng)調(diào)用view的setNeedsDisplay或者setNeedsDisplayInRect:方法時愧旦。

步驟:

  • 1.先在drawRect方法中獲得上下文context;
  • 2.繪制圖形(線定罢,圖形笤虫,圖片等);
  • 3.設(shè)置一些修飾屬性祖凫;
  • 4.渲染到上下文琼蚯,完成繪圖。
#import "CustomView.h"

@implementation CustomView

- (void)drawRect:(CGRect)rect
{
    // 1.獲取上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    // --------------------------實心圓
    
    // 2.畫圖
    CGContextAddEllipseInRect(ctx, CGRectMake(10, 10, 50, 50));
    [[UIColor greenColor] set];
    
    // 3.渲染
    CGContextFillPath(ctx);
    
    
    
    // --------------------------空心圓
    
    CGContextAddEllipseInRect(ctx, CGRectMake(70, 10, 50, 50));
    [[UIColor redColor] set];
    CGContextStrokePath(ctx);
    
    
    
    // --------------------------橢圓
    //畫橢圓和畫圓方法一樣惠况,橢圓只是設(shè)置不同的長寬
    CGContextAddEllipseInRect(ctx, CGRectMake(130, 10, 100, 50));
    [[UIColor purpleColor] set];
    CGContextFillPath(ctx);
    
    
    
    // --------------------------直線
    CGContextMoveToPoint(ctx, 20, 80); // 起點
    CGContextAddLineToPoint(ctx, self.frame.size.width-10, 80); //終點
//    CGContextSetRGBStrokeColor(ctx, 0, 1.0, 0, 1.0); // 顏色
    [[UIColor redColor] set]; // 兩種設(shè)置顏色的方式都可以
    CGContextSetLineWidth(ctx, 2.0f); // 線的寬度
    CGContextSetLineCap(ctx, kCGLineCapRound); // 起點和重點圓角
    CGContextSetLineJoin(ctx, kCGLineJoinRound); // 轉(zhuǎn)角圓角
    CGContextStrokePath(ctx); // 渲染(直線只能繪制空心的遭庶,不能調(diào)用CGContextFillPath(ctx);)
    
    
    
    // --------------------------三角形
    CGContextMoveToPoint(ctx, 10, 150); // 第一個點
    CGContextAddLineToPoint(ctx, 60, 100); // 第二個點
    CGContextAddLineToPoint(ctx, 100, 150); // 第三個點
    [[UIColor purpleColor] set];
    CGContextClosePath(ctx);
    CGContextStrokePath(ctx);
    
    
    
    // --------------------------矩形
    CGContextAddRect(ctx, CGRectMake(20, 170, 100, 50));
    [[UIColor orangeColor] set];
//    CGContextStrokePath(ctx); // 空心
    CGContextFillPath(ctx);
    
    
    
    // --------------------------圓弧
    CGContextAddArc(ctx, 200, 170, 50, M_PI, M_PI_4, 0);
    CGContextClosePath(ctx);
    CGContextFillPath(ctx);
    
    
    // --------------------------文字
    NSString *str = @"你在紅樓,我在西游";
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    dict[NSForegroundColorAttributeName] = [UIColor whiteColor]; // 文字顏色
    dict[NSFontAttributeName] = [UIFont systemFontOfSize:14]; // 字體
    
    [str drawInRect:CGRectMake(20, 250, 300, 30) withAttributes:dict];
    

    // --------------------------圖片
    UIImage *img = [UIImage imageNamed:@"yingmu"];
//    [img drawAsPatternInRect:CGRectMake(20, 280, 300, 300)]; // 多個平鋪
//    [img drawAtPoint:CGPointMake(20, 280)]; // 繪制到指定點稠屠,圖片有多大就顯示多大
    [img drawInRect:CGRectMake(20, 280, 80, 80)]; // 拉伸
}

繪圖它能干什么罚拟?為什么要學(xué)習(xí)它?

我們常用繪圖來自定義一些視圖控件完箩,以達到我們個性化的需求赐俗。
若自定義視圖控件:我們可以子類化一個UIView,然后重寫它的drawRect方法弊知。在drawRect里進行圖形繪制阻逮,從而實現(xiàn)自定義控件,完成酷炫個性化的控件秩彤。

結(jié)尾

關(guān)于繪圖叔扼,其實在我當(dāng)前接觸的項目中用得很少,但是以后肯定會接觸到漫雷。像這種不常用但比較重要的內(nèi)容瓜富,我覺得要做到初步理解,然后梳理總結(jié)降盹,到最后深度理解与柑。所以寫這篇文章。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市价捧,隨后出現(xiàn)的幾起案子丑念,更是在濱河造成了極大的恐慌,老刑警劉巖结蟋,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脯倚,死亡現(xiàn)場離奇詭異,居然都是意外死亡嵌屎,警方通過查閱死者的電腦和手機推正,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宝惰,“玉大人植榕,你說我怎么就攤上這事≌撇猓” “怎么了内贮?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵产园,是天一觀的道長汞斧。 經(jīng)常有香客問我,道長什燕,這世上最難降的妖魔是什么粘勒? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮屎即,結(jié)果婚禮上庙睡,老公的妹妹穿的比我還像新娘。我一直安慰自己技俐,他們只是感情好乘陪,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著雕擂,像睡著了一般啡邑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上井赌,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天谤逼,我揣著相機與錄音,去河邊找鬼仇穗。 笑死流部,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纹坐。 我是一名探鬼主播枝冀,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宾茂?” 一聲冷哼從身側(cè)響起瓷马,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎跨晴,沒想到半個月后欧聘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡端盆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年怀骤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片焕妙。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡蒋伦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出焚鹊,到底是詐尸還是另有隱情痕届,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布末患,位于F島的核電站研叫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏璧针。R本人自食惡果不足惜嚷炉,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望探橱。 院中可真熱鬧申屹,春花似錦、人聲如沸隧膏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胞枕。三九已至杆煞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曲稼,已是汗流浹背索绪。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留贫悄,地道東北人瑞驱。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像窄坦,于是被迫代替她去往敵國和親唤反。 傳聞我的和親對象是個殘疾皇子凳寺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

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