iOS 2D繪圖詳解(Quartz 2D)之概述

來源:互聯網
上載者:User

iOS 2D繪圖詳解(Quartz 2D)之概述

 

前言:最近在研究自訂控制項,由於想要徹底的定製控制項的視圖還是要繼承UIView,雖然對CALayer及其子類很熟練,但是對Quartz 2D這個強大的架構仍然概念模稜兩可。於是,決定學習下,暫訂7篇文章講解,會寫一些Demo。
官方文檔

本文的代碼Demo在最後一部分

Quartz 2D用來幹嘛的?

Quartz 2D屬於Core Graphics(所以大多數相關方法的都是以CG開頭),是iOS/Mac OSX 提供的在核心之上的強大的2D繪圖引擎,並且這個繪圖引擎是裝置無關的。也就是說,不用關心裝置的大小,裝置的解析度,只要利用Quartz 2D,這些裝置相關的會自動處理。Quartz 2D能夠提供的強大功能如下

透明層(transparency layers) 陰影 基於path的繪圖(path-based drawing) 離屏渲染(offscreen rendering) 複雜的顏色處理(advanced color management) 消除鋸齒渲染(anti-aliased rendering) PDF建立,展示,解析(這部分不在這個系列之中) 配合Core Animation, OpenGL ES,UIKit完成複雜的功能畫板-The Graphics Context

既然提到繪圖,那自然有一個容器來包含繪製的結果,然後把這個結果渲染到螢幕上去,而Quartz 2D的容器就是CGContextRef資料模型。這種資料模型是C的結構體,儲存了渲染到螢幕上需要的一切資訊。
那麼,最後 Graphics Context 可以渲染到哪裡呢?

Layer Window 印表機 PDF Bitmap(圖片)

繪製模型

Quartz 2D採用painter’s model,意味著每一次繪製都是一層,然後按照順序一層層的疊加到畫板上。例如

資料類型

Quartz 2D中的資料類型都是透明的,也就是說使用者只需要使用即可,不需要實際訪問其中的變數。具體的資料類型包括

CGPathRef 路徑類型,用來繪製路徑(注意帶有ref尾碼的一般都是繪製的畫板) CGImageRef,繪製bitmap CGLayerRef,繪製layer,layer可複用,可離屏渲染 CGPatternRef,重複繪製 CGShadingRef和CGGradientRef,繪製漸層(例如色彩坡形) CGFunctionRef,定義回呼函數,CGShadingRef和CGGradientRef的輔助類型 CGColorRef and CGColorSpaceRef,定義如何處理顏色 CGFontRef,繪製文字 其他類型(pdf這個系列不講解,所以不會涉及)繪製狀態

在使用quartz 2d進行繪圖的時候,經常需要設定顏色,字型,設定context的座標原點變換,context旋轉。這些影響的都是當前繪製狀態。Context中利用堆棧的方式來儲存繪製狀態。調用CGContextSaveGState來儲存當前繪製狀態的copy到堆棧中,利用CGContextRestoreGState彈出堆棧最頂層的繪製狀態,設定為當前的繪製狀態。注意,不是所有的參數都會儲存,以下表格中的參數會儲存

座標系

和UIKit的座標系不一樣,Quartz 2D的座標系是在左下角的。

Quartz利用座標系的旋轉位移等操作來繪製複雜的動畫。
但是有兩個地方的座標系是正常的UIKit座標系

UIView 的context 通過這個方法UIGraphicsBeginImageContextWithOptions返回的context
一個簡單的Demo講解

建立一個UIView的子類,然後重寫drawRect

- (void)drawRect:(CGRect)rect {    CGContextRef context = UIGraphicsGetCurrentContext();    CGContextSetFillColorWithColor(context, [UIColor lightGrayColor].CGColor);    CGContextFillRect(context, rect);//先填充整個地區    CGRect testRect = CGRectMake(10, 10, 20, 20);    CGContextAddRect(context, testRect);    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);//修改畫筆顏色    CGContextFillRect(context, testRect);//填充部分地區}

然後,這樣調用

    LeoDemoView * demoView = [[LeoDemoView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];    [self.view addSubview:demoView];

效果

可以看到座標系是正常的UIKit座標系

然後,我們在在上面繪製一個文字”Leo”,在上述drawRect的最後添加,<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHByZSBjbGFzcz0="brush:java;"> NSString * toDraw = @Leo; [toDraw drawAtPoint:CGPointMake(CGRectGetWidth(rect)/2, CGRectGetHeight(rect)/2) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12],NSForegroundColorAttributeName:[UIColor greenColor]}];

可以看到,繪製是一層一層覆蓋的,

最後,我們在右下角繪製一個紅心,但是希望紅心是反過來的。這裡用到了上文的所說的繪製狀態堆棧。繼續在drawRect的最後添加如下代碼

    CGContextSaveGState(context);    CGContextTranslateCTM(context,rect.size.width,rect.size.height);    CGContextRotateCTM(context, M_PI);    NSString * redHeart = @??;//MarkDown 顯示不出紅心    [redHeart drawAtPoint:CGPointMake(0, 0) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15]}];    CGContextRestoreGState(context);}

效果

這裡,初學者可能不懂到底是怎麼回事了。我通過圖解的方式一步步解釋

這行代碼把座標系移動到右下角
CGContextTranslateCTM(context,rect.size.width,rect.size.height);

接著把座標系逆時針旋轉180度

    CGContextRotateCTM(context, M_PI);

這時候的座標系

這時候,參考這個座標系進行繪製,看到的就是反過來的。哇哢哢!

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.