Quartz2D

Quartz2D

Quartz2D概述

  • Quartz2D可以完成什么:
    • 繪制圖形:線,三角形,圓,橢圓等等
    • 繪制文字(在image上)
    • 繪制\生成圖片
    • 繪制\生成PDF
    • 剪裁\切割圖片
    • 自定義UI控件
    • 手勢解鎖
  • 什么是圖形上下文(Graphics Context):
    • 是一個CGContextRef類型的數(shù)據(jù)
    • 保存繪制的信息和狀態(tài)(我們也可以理解成是一個畫布,在這個畫布上繪制)
    • 決定繪制的輸出目標(繪制到什么地方去?)(輸出目標可以是PDF文件芭碍、Bitmap或者顯示器的窗口上)
  • Quartz2D可以獲取到的圖形上下文
    • Bitmap Graphics Context
    • PDF Graphics Context
    • Window Graphics Context
    • Layer Graphics Context
    • Printer Graphics Context
1.png

Quartz2D對于圖形的應(yīng)用

Quartz2D的基本用法

  • 在Quartz2D中蘋果為我們提供了一套CoreGraphics框架,這是一套c語言的框架,下面的前兩種方式就是采用這套,最后一種方式是在前面方式的基礎(chǔ)上在OC中封裝的一個類
  • 無論是哪個方法,都必須在drawRect方法中執(zhí)行,因為在drawRect方法中才能獲取上下文

CGPath繪制

//CGPath繪制
- (void)CGPath
{
    //獲取圖形上下文
    CGContextRef ref = UIGraphicsGetCurrentContext();
    //初始化一條線路
    CGMutablePathRef pathref = CGPathCreateMutable();
    //設(shè)置起點
    //1.路徑 2.旋轉(zhuǎn),縮放,平移等 3.起點的x軸坐標 4.起點的y軸坐標
    CGPathMoveToPoint(pathref, nil, 10, 10);
    //設(shè)置終點
    CGPathAddLineToPoint(pathref, nil, 100, 100);
    //把這個路線放到上下文上
    //1.上下文 2.路徑
    CGContextAddPath(ref, pathref);
    //釋放路徑(凡是c語言函數(shù)中帶create,copy,一樣要釋放)
    CGPathRelease(pathref);
    //繪制
    CGContextStrokePath(ref);
    //填充
    //    CGContextFillPath(ref);

}

CGContexRef繪制

//CGContexRef繪制
- (void)CGContext
{

    //獲取圖形上下文
    CGContextRef ref  = UIGraphicsGetCurrentContext();
    // 設(shè)置起點
    CGContextMoveToPoint(ref, 10, 10);
    //設(shè)置終點(第一條線)
    CGContextAddLineToPoint(ref, 100, 100);
    //設(shè)置終點(第二條線)
    CGContextAddLineToPoint(ref, 10, 100);
    //設(shè)置線冒
    CGContextSetLineCap(ref, kCGLineCapRound);
    //設(shè)置拐角
    CGContextSetLineJoin(ref, kCGLineJoinRound);
    //設(shè)置線寬
    CGContextSetLineWidth(ref, 10.0f);
    //閉合
    CGContextClosePath(ref);
    //設(shè)置線的顏色
    CGContextSetStrokeColorWithColor(ref, [UIColor redColor].CGColor);
    //設(shè)置填充顏色
    CGContextSetFillColorWithColor(ref, [UIColor yellowColor].CGColor);
    //下面兩個誰在前面執(zhí)行那個
    //    //填充
    //    CGContextFillPath(ref);
    //    //繪制
    //    CGContextStrokePath(ref);
    //由于上面兩個方法只有一個能執(zhí)行,所以為了兩個都有效果,采用下面的方法,兩個都設(shè)置(枚舉)
    CGContextDrawPath(ref, kCGPathFillStroke);
}

UIBezierPath的基本用法

//貝瑟爾基本用法
- (void)bezier
{
    //初始化
    UIBezierPath *path = [[UIBezierPath alloc] init];
    //設(shè)置起點
    [path moveToPoint:CGPointMake(10, 10)];
    //設(shè)置終點(一條線)
    [path addLineToPoint:CGPointMake(100, 100)];
    //設(shè)置終點(第二條線)
    [path addLineToPoint:CGPointMake(10, 100)];
    //設(shè)置線寬
    [path setLineWidth:10.0f];
    //設(shè)直線冒
    [path setLineCapStyle:kCGLineCapRound];
    //設(shè)置拐角(兩條線才能有拐角)
    [path setLineJoinStyle:kCGLineJoinRound];
    //設(shè)直線的顏色
    [[UIColor redColor] setStroke];
    //設(shè)置填充顏色
    [[UIColor yellowColor] setFill];
    //閉合路徑
    [path closePath];
    //填充
    [path fill];
    //繪制
    [path stroke];
}
//利用貝瑟爾繪制圓,橢圓和扇形
- (void)drawRound
{
    //繪制圓
    UIBezierPath *path = [UIBezierPath bezierPath];
    //    1.圓心 2.半徑 3. 開始的值(PI/ 2) 4. 結(jié)束的值 5. yes: 逆時針繪制 no:順時針
    [path addArcWithCenter:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    //繪制
    [path stroke];
    //繪制橢圓
    UIBezierPath *path1 = [UIBezierPath  bezierPathWithOvalInRect:CGRectMake(10, 10, 100, 50)];
    //繪制
    [path1 stroke];
    //扇形
    UIBezierPath *path2  =[[UIBezierPath alloc] init];
    //設(shè)置起點
    [path2 moveToPoint:CGPointMake(100, 100)];
    [path2 addArcWithCenter:CGPointMake(100, 100) radius:100 startAngle:0 endAngle:M_PI / 2 clockwise:YES];
    //閉合
    [path2 closePath];
    //繪制
    [path2 stroke];
}

自定義View

  • 如何利用Quartz2D繪制東西到view上徒役?
    • 首先孽尽,得有圖形上下文,因為它能保存繪圖信息忧勿,并且決定著繪制到什么地方去
    • 其次杉女,那個圖形上下文必須跟view相關(guān)聯(lián),才能將內(nèi)容繪制到view上面
  • 自定義view的步驟
    • 新建一個類鸳吸,繼承自UIView
    • 實現(xiàn)- (void)drawRect:(CGRect)rect方法熏挎,然后在這個方法中
    • 取得跟當(dāng)前view相關(guān)聯(lián)的圖形上下文
    • 繪制相應(yīng)的圖形內(nèi)容
    • 利用圖形上下文將繪制的所有內(nèi)容渲染顯示到view上面
  • 注意:drawRect方法在view第一次顯示到屏幕上會調(diào)用,在ViewDidLoad之后,viewWillAppear之前,如果想要在改變圖形上下文之后調(diào)用drawRect方法顯示改變后的效果,用setNeedsDisplay方法,調(diào)用完setNeedsDisplay方法之后,drawRect會被調(diào)用一次

繪制餅狀圖

  • 基本思路:可以封裝一個類繼承與UIView,也可以給UIView寫一個分類,這里采用繼承
//在外部留好接口:傳入數(shù)據(jù)和餅狀圖劃分的顏色,以數(shù)組形式傳入
@interface NewView : UIView
/**  數(shù)字數(shù)組 */
@property (nonatomic,strong) NSMutableArray *numberArray;
/**  顏色數(shù)組 */
@property (nonatomic,strong) NSMutableArray *colorArray;
/**  圓心 */
@property (nonatomic,assign) CGPoint centerPoint;
@end
//在.m中的drawRect方法中繪制
- (void)drawRect:(CGRect)rect {
   //繪制圓
    CGContextRef ref = UIGraphicsGetCurrentContext();
    //設(shè)置圓心
   CGPoint centerPoint = self.centerPoint;
    //設(shè)置一個半徑
    CGFloat radius = 100;
    //設(shè)置起始點
    CGFloat starAngle = - M_PI_2;
    //計算總和
    CGFloat total = 0;
    for (NSNumber *num in self.numberArray) {
        total = total + [num floatValue];
    }
    //從頭開始一個一個繪制,利用for循環(huán)
    for (int i = 0; i < self.numberArray.count; i++) {
        //計算百分比
        CGFloat per =  [self.numberArray[i] floatValue] / total ;
        //設(shè)置終點
        CGFloat endAngle = starAngle + 2 * M_PI * per;
        //設(shè)置圓心為起點
        CGContextMoveToPoint(ref,centerPoint.x , centerPoint.y);
        //添加一條圓弧
        CGContextAddArc(ref, centerPoint.x, centerPoint.y, radius, starAngle, endAngle, NO);
        //閉合
        CGContextClosePath(ref);
        //設(shè)置填充顏色
        CGContextSetFillColorWithColor(ref, [(UIColor *)self.colorArray[i] CGColor]);
        //繪制
        CGContextDrawPath(ref, kCGPathFillStroke);
        //重置起點
        starAngle = endAngle;
    }
}

利用貝瑟爾曲線繪制曲線

- (void)drawRect:(CGRect)rect {
    // Drawing code
//二元
    UIBezierPath *path  =[[UIBezierPath alloc] init];
    //設(shè)置起點
    [path moveToPoint:CGPointMake(10, 10)];
    //設(shè)置曲線的屬性
    //參數(shù)1.曲線的終點,2.曲線的基準點
    [path addQuadCurveToPoint:CGPointMake(100,100) controlPoint:CGPointMake(50, 100)];
    //繪制
    [path stroke];
//    三元
    UIBezierPath *path  = [[UIBezierPath alloc] init];
    //設(shè)置起點
    [path moveToPoint:CGPointMake(10, 100)];
    //參數(shù)1.曲線的終點 2.曲線的第一個基準點 3.曲線的第二個基準點
    [path addCurveToPoint:CGPointMake(100, 100) controlPoint1:CGPointMake(35, 25) controlPoint2:CGPointMake(75, 175)];
    //繪制
    [path stroke];
}

Quartz2D對于圖片的應(yīng)用

  • 對于圖片來說獲取上下文可以不需要在drawRect中,有自己的獲取方式
  • 獲取圖片的上下文一定在 UIGraphicsBeginImageContext(),UIGraphicsEndImageContext()這兩個方法中寫,或者進行對圖片的裁剪,旋轉(zhuǎn),擦除等等.
  • 操作完圖片之后可以用UIGraphicsGetImageFromCurrentImageContext()方法獲得修改完之后的圖片
  • 除了圖片可以這樣修改,PDF格式也提供了類似的方法

根據(jù)顏色生成圖片

  • 實現(xiàn)原理:先獲取一個固定大小的上下文,根據(jù)傳進來的顏色,將上下文顏色填充,在image上平鋪,輸出image
//根據(jù)顏色生成圖片
- (UIImage *)getImageWithColor:(UIColor *)color
{
    //開始
//    1.圖片的尺寸,2.是否是不透明的,3.圖片的縮放比例
    UIGraphicsBeginImageContext(CGSizeMake(200, 50));
    //獲取上下文
    CGContextRef ref =  UIGraphicsGetCurrentContext();
    //設(shè)置顏色
    CGContextSetFillColorWithColor(ref, color.CGColor);
    //設(shè)置填充區(qū)域
    CGContextFillRect(ref, CGRectMake(0, 0, 100, 100));
    //填充
    CGContextDrawPath(ref, kCGPathFillStroke);
    //獲取圖片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    //結(jié)束
    UIGraphicsEndImageContext();
    //輸出圖片
    return image;
}

圖片的剪裁

//圖片的裁剪
- (UIImage *)clipWithImage:(UIImage *)image
{
    //獲取上下文(并給出這個上下文的尺寸)
    UIGraphicsBeginImageContext(CGSizeMake(image.size.width / 2.0, image.size.height));
    //這里的rect是值得在image的什么區(qū)域去繪制(下面這個寫其實是繪制在整個image中)
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    //結(jié)束
    UIGraphicsEndImageContext();
    //輸出圖片
    return UIGraphicsGetImageFromCurrentImageContext();
}

切圓

  • 實現(xiàn)原理:先畫出一個圓型的上下文,再講圖片畫到畫布上
//切圓
- (UIImage *)clipWithimage:(UIImage *)image
{
    UIGraphicsBeginImageContext(image.size);
    //獲取上下文
    CGContextRef ref = UIGraphicsGetCurrentContext();
    //畫圓
    CGContextAddArc(ref, image.size.width / 2.0, image.size.height / 2.0, image.size.height / 2.0, 0, M_PI * 2, NO);
    //裁剪畫布
    CGContextClip(ref);
    // 把圖片畫到畫布上
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    //結(jié)束
    UIGraphicsEndImageContext();
    //輸出并返回
    return  UIGraphicsGetImageFromCurrentImageContext();
}

圖片旋轉(zhuǎn),平移,縮放

//圖片旋轉(zhuǎn)
- (UIImage *)transWithImage:(UIImage *)image
{
    UIGraphicsBeginImageContext(image.size);
    //獲取上下文
    CGContextRef ref = UIGraphicsGetCurrentContext();
    //縮放(旋轉(zhuǎn)縮放平移是在上下文操作圖片)
    CGContextScaleCTM(ref, 0.6, 0.6);
    //平移
    CGContextTranslateCTM(ref, 50, 0);
    //旋轉(zhuǎn) 1.上下文 2.角度
    CGContextRotateCTM(ref, M_PI_4);
    //把圖片畫到畫布上
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    //結(jié)束
    UIGraphicsEndImageContext();
    //返回繪制的圖片
    return UIGraphicsGetImageFromCurrentImageContext();
}

圖片擦除(刮獎原理)(截屏也用到了這個的核心原理)

  • 實現(xiàn)原理:當(dāng)手指觸摸到屏幕上的時候,去到觸摸的某一個點,放大成一個正方形或者圓形,形成橡皮的感覺,在滑動過的區(qū)域?qū)D片刮除,顯示下面的label或者其他view,一定要保證刮除的我圖片一定是透明的,否則看不到下面的label或者view
- (void)viewDidLoad {
    [super viewDidLoad];
    //初始化要顯示在下面的提示label
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 200, 50)];
    label.textAlignment = NSTextAlignmentCenter;
    label.text = @"恭喜您中獎了";
    [self.view addSubview:label];
    //初始化顯示在上面的imageview(用上面的根據(jù)顏色生成圖片方法生成一個灰色的圖層,看起來像一種刮獎的圖層)
    self.imageView = [[UIImageView alloc] initWithImage:[self getImageWithColor:[UIColor grayColor]]];
    self.imageView.frame = CGRectMake(100, 100, 200, 50);
    [self.view addSubview:self.imageView];
}
//刮獎()
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = touches.anyObject;
    CGPoint point = [touch locationInView:self.imageView];
    //滑塊區(qū)域(觸碰到的點放大成正方形)
   CGRect rect =  CGRectMake( point.x - 10,point.y - 10, 20, 20);
    //獲取上下文(這里記得一定要透明)
    UIGraphicsBeginImageContextWithOptions(self.imageView.bounds.size, NO, 0);
   CGContextRef ref =  UIGraphicsGetCurrentContext();
    //把imageView的layer映射到上下文中(這個是核心,由于UIView本質(zhì)上顯示東西的layer層,所以實質(zhì)是將imageView顯示的東西全部復(fù)制給上下文,app中長用到的截屏就利用了這個原理)
    [self.imageView.layer renderInContext:ref];
    //清除劃過的區(qū)域
    CGContextClearRect(ref, rect);
    UIImage *image =UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    //返回圖片并不斷的傳給UIImageView上去顯示
    self.imageView.image = image;

}

繪制文字(以圖片的形式輸出)(給圖片右下角繪制專屬的唯一標示(也就是水印)就用到了這個原理)

//繪制文字
- (UIImage *)drawWithStr:(NSString *)str
{
    //獲取上下文
    UIGraphicsBeginImageContext(self.view.frame.size);
    //利用富文本設(shè)置文字的屬性
    NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:14.0f],NSForegroundColorAttributeName:[UIColor redColor]};
    //繪制在上下文中
    [str drawInRect:CGRectMake(10, 10, 200, 100) withAttributes:dic];
    //輸出image
    return UIGraphicsGetImageFromCurrentImageContext();
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市晌砾,隨后出現(xiàn)的幾起案子坎拐,更是在濱河造成了極大的恐慌,老刑警劉巖养匈,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哼勇,死亡現(xiàn)場離奇詭異,居然都是意外死亡呕乎,警方通過查閱死者的電腦和手機积担,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猬仁,“玉大人帝璧,你說我怎么就攤上這事∈簦” “怎么了的烁?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長诈闺。 經(jīng)常有香客問我渴庆,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任把曼,我火速辦了婚禮杨帽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嗤军。我一直安慰自己注盈,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布叙赚。 她就那樣靜靜地躺著老客,像睡著了一般。 火紅的嫁衣襯著肌膚如雪震叮。 梳的紋絲不亂的頭發(fā)上胧砰,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機與錄音苇瓣,去河邊找鬼尉间。 笑死,一個胖子當(dāng)著我的面吹牛击罪,可吹牛的內(nèi)容都是我干的哲嘲。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼媳禁,長吁一口氣:“原來是場噩夢啊……” “哼眠副!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起竣稽,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤囱怕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后毫别,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娃弓,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年拧烦,在試婚紗的時候發(fā)現(xiàn)自己被綠了忘闻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡恋博,死狀恐怖齐佳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情债沮,我是刑警寧澤炼吴,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站疫衩,受9級特大地震影響硅蹦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一童芹、第九天 我趴在偏房一處隱蔽的房頂上張望涮瞻。 院中可真熱鬧,春花似錦假褪、人聲如沸署咽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宁否。三九已至,卻和暖如春缀遍,著一層夾襖步出監(jiān)牢的瞬間慕匠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工域醇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留台谊,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓歹苦,卻偏偏與公主長得像青伤,于是被迫代替她去往敵國和親督怜。 傳聞我的和親對象是個殘疾皇子殴瘦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

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

  • Quartz2D以及drawRect的重繪機制字數(shù)1487 閱讀21 評論1 喜歡1一、什么是Quartz2D Q...
    PurpleWind閱讀 762評論 0 3
  • 什么是Quartz2D 是一個二維的繪圖引擎,同時支持iOS和Mac系統(tǒng) Quartz2D的API是純C語言的,它...
    Mario_ZJ閱讀 577評論 0 1
  • Quartz2D 簡介 Quartz2D是二維(平面)的繪圖引擎(經(jīng)包裝的函數(shù)庫号杠,方便開發(fā)者使用蚪腋。也就是說蘋果幫我...
    iOS_Cqlee閱讀 628評論 0 2
  • 一、什么是Quartz2D Quartz2D是?個二維繪圖引擎,同時支持iOS和Mac系統(tǒng)Quartz2D的API...
    CoderZb閱讀 2,284評論 4 17
  • 天吶姨蟋,到底怎么了屉凯,他到底怎么了
    丫頭Alisa閱讀 159評論 0 0