引子 PD:我們需要的界面大概是這樣子的,可以實(shí)現(xiàn)嗎? 技術(shù):ok,這個(gè)界面很簡單,我們用基本的view就可以實(shí)現(xiàn)。 數(shù)日后 UED:我們的設(shè)計(jì)是這樣子的 技術(shù):呃,晴天霹靂啊,為什么搞的這么復(fù)雜,又要弧度,又要曲線?為什么不能用標(biāo)準(zhǔn)的框架來 UED:這就是藝術(shù),激烈而又平滑的過渡才能彰顯她旺盛的生命力,而明暗錯(cuò)落的顏色賦予了她燃燒不盡的激情,仿佛一個(gè)少女,身材高挑、烈焰紅唇...... 技術(shù):就不能少搞些奇技淫巧嗎,我已經(jīng)連吐槽的力氣都沒有了... 相信每個(gè)前端開發(fā)都有過這樣的經(jīng)歷,我們認(rèn)為可以用通用視圖解決的需求,視覺非要加上點(diǎn)特殊的元素,不規(guī)則圖形、不均勻顏色。做為一個(gè)有追求的Coder雖然嘴上說著不要,但身體卻很誠實(shí)的去查資料。google一下iOS 繪圖,各種繪圖的技術(shù)簡介和demo就搜出來了,隨之而來的是各種意思好像都差不多,好像不是一回事的名詞:UIBezierPath 、Quartz、Quartz 2D 、QuartzCore、Core Graphic、OpenGL 、OpenGL ES...... 此時(shí)的我是這樣子的 完全搞不懂到底在哪種場景下應(yīng)該使用哪種技術(shù),有木有。本文的目的就是梳理在iOS平臺(tái)中供開發(fā)人員使用的繪圖框架以及他們之間的恩怨糾葛,以便選擇最合適的技術(shù)框架完成需求。 iOS、MacOS系統(tǒng)圖形架構(gòu) 由此圖可見:
UIBezierPath 用于創(chuàng)建基于矢量的路徑,如圓形、橢圓形和矩形,或者由多個(gè)直線和曲線組成的形狀。繪圖步驟也非常的簡單:
UIBezierPath繪制圖形代碼 //繪制圓形 Quartz 在介紹 Core Graphics 之前,我們先把 Quartz 的概念理順清楚。嫌啰嗦可以直接拉到下面看結(jié)論 簡單來說:
那么Quartz同OpenGL是什么關(guān)系呢?他的底層是否通過OpenGL調(diào)用GPU? 結(jié)論
Core Graphics Core Graphics是基于Quartz框架的高保真輸出2D圖形的渲染引擎??商幚砘诼窂降睦L圖、抗鋸齒渲染、漸變、圖像、顏色管理、PDF文檔等。 Core Graphics提供了一套2D繪圖功能的C語言API,使用C結(jié)構(gòu)體和C的函數(shù)模擬了一套面向?qū)ο蟮木幊虣C(jī)制。Core Graphics中沒有OC的對象和方法。 無論圖片、PDF還是視圖的圖層,都是由CoreGraphics框架完成繪制的。UIImage、UIBezierPath和NSString都提供了至少一種用于在drawRect:中繪圖的方法,實(shí)現(xiàn)原理是將Core Graphics代碼封裝在其中,降低繪圖難度。 Context CoreGraphics中最重要的對象是graphics context,既圖形上下文。context是CGContextRef的對象,負(fù)責(zé)存儲(chǔ)繪畫狀態(tài)和繪制內(nèi)存所處的內(nèi)存空間。 我以前一直無法很好的理解Context,后來接觸Android繪圖的時(shí)候發(fā)現(xiàn)Android沒有這個(gè)東西。Android的2D圖形繪制通過Canvas和Paint實(shí)現(xiàn)的。Android的繪圖框架理解起來就非常的容易,你想畫圖首先你要有畫的地方Canvas,其次你要有筆Paint。而在iOS中Context就是要畫圖的畫板和畫筆。 Core Graphics繪制圖形代碼 //繪制圓形 Core Graphics的Ref后綴類型 帶有Ref后綴的類型是CoreGraphics中用來模擬面向?qū)ο髾C(jī)制的C結(jié)構(gòu)。CoreGraphics對象是在堆上分配內(nèi)存,因此創(chuàng)建CoreGraphics對象時(shí),會(huì)返回一個(gè)指向?qū)ο髢?nèi)存地址的指針。 使用這種分配方式的C結(jié)構(gòu)都有一個(gè)用來表示結(jié)構(gòu)指針的類型定義(type definition)。例如,CGColor結(jié)構(gòu),不會(huì)被直接使用的類型,有一個(gè)表示Color * 的類型定義—CGColorRef,用來被使用的類型。使用這種類型定義是為了區(qū)分指針變量,方便開發(fā)者判斷指針變量是指向C結(jié)構(gòu)還是可以接收消息的Objective-C對象。 CGRect和CGPoint這種比較簡單直接在棧上分配的結(jié)構(gòu)體,不需要使用結(jié)構(gòu)指針,因此類型名稱后不帶Ref后綴。 帶有Ref后綴的類型的對象可能是強(qiáng)引用指針,成為指向?qū)ο蟮膿碛姓摺RC是無法識(shí)別Core對象的所有權(quán),必須在使用后手動(dòng)釋放。規(guī)則是,如果使用名稱中帶有create或者copy的函數(shù)創(chuàng)建了一個(gè)CoreGraphics對象,就必須調(diào)用Release函數(shù)并傳入該對象的指針。 Core Graphics 能完成的工作
Core Graphics相比UIBezierPath在使用上更復(fù)雜一些,但是支持的效果也更多,程序運(yùn)行效率更高。所以現(xiàn)在iOS系統(tǒng)上繪圖需求基本上都使用Core Graphis來完成。 OpenGL && OpenGL ES OpenGL ES 是OpenGL 三維圖形API的子集,針對嵌入式操作系統(tǒng)設(shè)計(jì)。iOS和Android都在系統(tǒng)內(nèi)集成了OpenGL ES。所以針對OpenGL ES 的代碼可以實(shí)現(xiàn)跨平臺(tái),大多數(shù)游戲框架都基于OpenGL。 OpenGL編程流程 1、編寫shader腳本
2、創(chuàng)建shader實(shí)例
3、創(chuàng)建program實(shí)例
裝載OpenGL shader 、創(chuàng)建OpenGL program示例代碼 - (void)setupProgram iOS系統(tǒng)使用OpenGL編程流程 1、設(shè)置CAEAGLLayer CAEAGLLayer是iOS中用于呈現(xiàn)OpenGL ES的渲染內(nèi)容的 2、設(shè)置EAGLContext OpenGL ES 渲染上下文。這個(gè)context管理所有使用OpenGL ES 進(jìn)行描繪的狀態(tài),命令以及資源信息。 3、創(chuàng)建Renderbuffer 緩沖區(qū)用于存儲(chǔ)繪圖數(shù)據(jù),Render Buffer有三種類型,分別是color、depth、stencil buffer 4、創(chuàng)建Framebuffer object Framebuffer object是buffer的管理者,color、depth、stencil可以添加到一個(gè)Framebuffer object上 5、銷毀Renderbuffer和Framebuffer 當(dāng)UIView變化后,layer的寬高也隨之變化,導(dǎo)致原來的renderbuffer 不再相符,需要銷毀既有 renderbuffer 和 framebuffer iOS系統(tǒng)調(diào)用OpenGL示例代碼 //在iOS設(shè)備中通過CAEAGLLayer使用OpenGL接口渲染內(nèi)容 示例代碼地址: http://gitlab./xunfeng.zy/opengl/blob/master/OpenGLDemo/ 結(jié)論 UIBezierPath的優(yōu)勢是方便,能用最少的代碼得要想要的圖形,并且不需要管理圖形上下文、緩沖區(qū)等容易出問題的地方,只需要關(guān)注圖形本身就行了。最主要的缺點(diǎn)是支持的效果有限,當(dāng)需要實(shí)現(xiàn)一些復(fù)雜圖形、復(fù)雜漸變效果的時(shí)候就無能為力了。所以如果只是一個(gè)簡單的圖形沒有特別的要求,可以用UIBezierPath實(shí)現(xiàn)。 Core Graphics的功能就比UIBezierPath強(qiáng)大很多,使用起來也更復(fù)雜,而且需要自己管理圖形上下文,需要投入更多的開發(fā)工作量。在效率和可做更多工作這兩個(gè)方面上Core Graphics全面壓制UIBezierPath,所以如果是復(fù)雜的圖形、多個(gè)圖形疊加、多種顏色漸變等需求可以使用Core Graphics實(shí)現(xiàn)。 OpenGL ES是直接操作GPU繪圖,而Core Graphics框架是先把命令輸入到CPU再調(diào)用GPU繪圖。很明顯OpenGL ES繪圖的效率更高,使用OpenGL ES繪圖也可以實(shí)現(xiàn)跨平臺(tái),而Core Graphics只能在iOS系統(tǒng)中使用。相比Core Graphics只支持2D繪圖,OpenGL ES對2D\3D都有很好的支持。 可見OpenGL ES是全方面的碾壓Core Graphics,但是除了特別大的圖片運(yùn)算需求外,我們很少使用OpenGL ES。其實(shí)上面的示例代碼已經(jīng)很好的說明了,繪制同一個(gè)圖形UIBezierPath需要5行代碼,Core Graphics需要10行代碼,雖然Core Graphics明顯比UIBezierPath工作量大,但還是同一個(gè)數(shù)量級(jí)的。 而使用OpenGL ES繪制,算上Vertex Shader和Fragment Shader繪制一個(gè)圖形要300~400行代碼。整整增加了兩個(gè)數(shù)量級(jí)。再加上調(diào)試、debug的工作量,就算有跨平臺(tái)的加成也無法抵消增加的時(shí)間成本。想使用OpenGL進(jìn)行繪圖,基本上都需要二次封裝,這也是為什么我們在繪圖的時(shí)候一般首選Core Graphics。 作者:darcy87 |
|