版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2018.09.06 |
前言
Quartz 2D
框架相信大家都知道,也都一直在使用。Quartz 2D
的API是純C語言的猜丹,它是一個(gè)二維繪圖引擎,同時(shí)支持iOS和Mac系統(tǒng)硅卢。Quartz 2D
的API來自于Core Graphics
框架射窒,數(shù)據(jù)類型和函數(shù)基本都以CG作為前綴藏杖,接下來幾篇我們就一起來看一下這個(gè)框架。感興趣可以看上面幾篇文章脉顿。
1. Quartz 2D編程指南 (一) —— 簡(jiǎn)介(一)
2. Quartz 2D編程指南 (二) —— Quartz 2D概覽(二)
3. Quartz 2D編程指南 (三) —— 圖形上下文(三)
4. Quartz 2D編程指南 (四) —— Paths路徑(一)
5. Quartz 2D編程指南 (五) —— Paths路徑(二)
6. Quartz 2D編程指南 (六) —— 顏色和顏色空間(一)
7. Quartz 2D編程指南 (七) —— 變換(一)
8. Quartz 2D編程指南 (八) —— Patterns圖案樣式(一)
9. Quartz 2D編程指南 (九) —— 陰影(一)
Gradients - 漸變
Quartz提供了兩種不透明的數(shù)據(jù)類型來創(chuàng)建漸變 - CGShadingRef
和CGGradientRef
蝌麸。您可以使用其中任何一個(gè)來創(chuàng)建軸向或徑向漸變。漸變是從一種顏色到另一種顏色不同的填充弊予。
軸向梯度(也稱為線性梯度)(axial gradient (also called a linear gradient))
沿著兩個(gè)限定的端點(diǎn)之間的軸變化祥楣。位于垂直于軸的直線上的所有點(diǎn)具有相同的顏色值开财。
徑向梯度(radial gradient)
是沿兩個(gè)限定端之間的軸徑向變化的填充汉柒,其通常是兩個(gè)圓。如果點(diǎn)位于中心點(diǎn)落在軸上的圓周上责鳍,則它們共享相同的顏色值碾褂。梯度的圓形截面的半徑由端圓的半徑限定;每個(gè)中間圓的半徑從一端到另一端線性變化历葛。
本章提供了可以使用Quartz創(chuàng)建的各種線性和徑向漸變的示例正塌,比較了繪制漸變時(shí)可以采用的兩種方法,然后展示了如何使用每種不透明數(shù)據(jù)類型來創(chuàng)建漸變恤溶。
Axial and Radial Gradient Examples - 軸向和徑向漸變示例
Quartz
函數(shù)提供了豐富的詞匯表來創(chuàng)建漸變效果乓诽。 本節(jié)介紹了您可以實(shí)現(xiàn)的一些結(jié)果。 圖8-1中的軸向漸變?cè)谝粋€(gè)端點(diǎn)(橙色陰影)和另一個(gè)端點(diǎn)(黃色陰影)之間變化咒程。 在這種情況下鸠天,軸相對(duì)于原點(diǎn)成45度角。
Quartz還允許您沿軸指定顏色和位置帐姻,以創(chuàng)建更復(fù)雜的軸向漸變稠集,如圖8-2所示。 起點(diǎn)處的顏色為紅色饥瓷,終點(diǎn)處的顏色為紫色剥纷。 但是,軸上還有五個(gè)位置呢铆,其顏色分別設(shè)置為橙色晦鞋,黃色,綠色棺克,藍(lán)色和靛藍(lán)悠垛。 您可以將結(jié)果視為沿同一軸的六個(gè)連續(xù)線性漸變。 雖然這里使用的軸與圖8-1(45度角)中使用的軸相同逆航,但并非必須如此鼎文。 軸的角度由您提供的起點(diǎn)和終點(diǎn)定義。
圖8-3顯示了一個(gè)徑向漸變因俐,它在一個(gè)小的亮紅色圓圈和一個(gè)較大的黑色圓圈之間變化拇惋。
使用Quartz周偎,您不僅可以根據(jù)顏色變化創(chuàng)建漸變;您也可以根據(jù)alpha改變?nèi)?chuàng)建撑帖,或者可以改變alpha和其他顏色組件蓉坎。 圖8-4顯示了一個(gè)漸變,當(dāng)alpha值從1.0到0.1變化時(shí)胡嘿,紅色蛉艾,綠色和藍(lán)色分量保持不變。
注意:如果使用alpha更改漸變衷敌,則在繪制到PDF內(nèi)容時(shí)將無法捕獲該漸變勿侯。 因此,不能打印這樣的漸變缴罗。 如果需要為PDF繪制漸變助琐,請(qǐng)使用1.0的alpha。
您可以將圓放置在徑向漸變中以創(chuàng)建各種形狀面氓。 如果一個(gè)圓部分或完全位于另一個(gè)圓之外兵钮,則Quartz為具有不等圓周的圓形創(chuàng)建圓錐曲面,為圓周具有相等圓周的圓柱曲面創(chuàng)建圓錐曲面舌界。 徑向漸變的常見用法是創(chuàng)建陰影球體掘譬,如圖8-5所示。 在這種情況下呻拌,單個(gè)點(diǎn)(半徑為0的圓)位于較大的圓內(nèi)葱轩。
您可以通過嵌套幾個(gè)類似于圖8-6中所示形狀的徑向漸變來創(chuàng)建更復(fù)雜的效果。 形狀的環(huán)形部分使用同心圓形成柏锄。
A Comparison of CGShading and CGGradient Objects - CGShading和CGGradient對(duì)象的比較
有兩種類型的對(duì)象可用于創(chuàng)建漸變酿箭,您可能想知道哪一個(gè)最適合使用。本節(jié)有助于回答這個(gè)問題趾娃。
CGShadingRef
不透明數(shù)據(jù)類型使您可以控制如何計(jì)算漸變中每個(gè)點(diǎn)的顏色缭嫡。在創(chuàng)建CGShading對(duì)象之前,必須創(chuàng)建一個(gè)CGFunction
對(duì)象(CGFunctionRef)抬闷,該對(duì)象定義用于計(jì)算漸變中顏色的函數(shù)妇蛀。編寫自定義函數(shù)可讓您自由創(chuàng)建平滑漸變,如圖8-1笤成,圖8-3和圖8-5所示评架,或更多非常規(guī)效果,如圖8-12所示炕泳。
創(chuàng)建CGShading
對(duì)象時(shí)纵诞,可以指定它是軸向(線性)還是徑向。與漸變計(jì)算函數(shù)(封裝為CGFunction
對(duì)象)一起培遵,您還可以提供顏色空間浙芙,起點(diǎn)和終點(diǎn)登刺,具體取決于您是繪制軸向還是徑向漸變。在繪圖時(shí)嗡呼,您只需將CGShading
對(duì)象與繪圖上下文一起傳遞給函數(shù)CGContextDrawShading纸俭。 Quartz為漸變中的每個(gè)點(diǎn)調(diào)用漸變計(jì)算函數(shù)。
CGGradient
對(duì)象是CGShading
對(duì)象的一個(gè)??子集南窗,其設(shè)計(jì)考慮了易用性揍很。 CGGradientRef
不透明數(shù)據(jù)類型很容易使用,因?yàn)镼uartz會(huì)為您計(jì)算漸變中每個(gè)點(diǎn)的顏色 - 您不提供漸變計(jì)算函數(shù)万伤。創(chuàng)建漸變對(duì)象時(shí)窒悔,可以提供位置和顏色的數(shù)組。 Quartz使用您為每個(gè)位置指定的顏色作為漸變的終點(diǎn)壕翩,為每組連續(xù)位置計(jì)算漸變蛉迹。您可以將漸變對(duì)象設(shè)置為使用單個(gè)起始和結(jié)束位置,如圖8-1所示放妈,或者您可以提供許多點(diǎn)來創(chuàng)建類似于圖8-2中所示的效果。提供兩個(gè)以上位置的能力優(yōu)于使用CGShading
對(duì)象荐操,后者僅限于兩個(gè)位置芜抒。
創(chuàng)建CGGradient
對(duì)象時(shí),只需為每個(gè)位置設(shè)置顏色空間托启,位置和顏色宅倒。使用漸變對(duì)象繪制上下文時(shí),可以指定Quartz是應(yīng)繪制軸向還是徑向漸變屯耸。在繪制時(shí)拐迁,您可以指定起始點(diǎn)和結(jié)束點(diǎn)或半徑,具體取決于您是繪制軸向還是徑向漸變疗绣,與CGShading
對(duì)象不同线召,CGShading
對(duì)象的幾何圖形是在創(chuàng)建時(shí)定義的,而不是在繪制時(shí)定義的多矮。
表8-1總結(jié)了兩種不透明數(shù)據(jù)類型之間的差異缓淹。
Table 8-1 Differences between CGShading and CGGradient objects
Extending Color Beyond the End of a Gradient - 在漸變結(jié)束之外延伸顏色
創(chuàng)建漸變時(shí),可以選擇使用純色填充漸變末端之外的空間塔逃。 Quartz使用在漸變邊界處定義的顏色作為填充顏色讯壶。 您可以延伸到漸變的開始,漸變的結(jié)束或兩者湾盗。 您可以將該選項(xiàng)應(yīng)用于使用CGShading
對(duì)象或CGGradient
對(duì)象創(chuàng)建的軸向或徑向漸變伏蚊。 每種類型的對(duì)象都提供了可用于設(shè)置擴(kuò)展選項(xiàng)的常量,如Using a CGGradient Object和Using a CGShading Object中所示格粪。
圖8-7顯示了在起始位置和結(jié)束位置都延伸的軸向梯度躏吊。 圖中的線顯示了漸變的軸肺孵。 如您所見,填充顏色對(duì)應(yīng)于起點(diǎn)和終點(diǎn)的顏色颜阐。
圖8-8將不使用擴(kuò)展選項(xiàng)的徑向漸變與使用擴(kuò)展選項(xiàng)的徑向漸變比較起始位置和結(jié)束位置平窘。 Quartz采用起始和結(jié)束顏色值,并使用這些純色來擴(kuò)展表面凳怨,如圖所示瑰艘。 該圖顯示了起始圓和結(jié)束圓,以及漸變的軸肤舞。
Using a CGGradient Object - 使用CGGradient對(duì)象
CGGradient
對(duì)象是漸變的抽象定義 - 它只是指定顏色和位置紫新,而不是幾何。您可以將同一個(gè)對(duì)象用于軸向和徑向幾何李剖。作為一個(gè)抽象定義芒率,CGGradient
對(duì)象可能比其對(duì)應(yīng)的CGShading
對(duì)象更容易重用。沒有將幾何體鎖定在CGGradient
對(duì)象中允許基于相同的顏色方案迭代地繪制漸變的可能性篙顺,而不需要在多個(gè)CGGradient
對(duì)象中占用存儲(chǔ)器資源偶芍。
因?yàn)?code>Quartz為您計(jì)算漸變,使用CGGradient
對(duì)象創(chuàng)建和繪制漸變非常簡(jiǎn)單德玫,需要以下步驟:
- 1) 創(chuàng)建一個(gè)
CGGradient
對(duì)象匪蟀,提供一個(gè)顏色空間,一個(gè)包含兩個(gè)或多個(gè)顏色組件的數(shù)組宰僧,一個(gè)包含兩個(gè)或多個(gè)位置的數(shù)組材彪,以及兩個(gè)或多個(gè)數(shù)組中每個(gè)數(shù)組中的項(xiàng)目數(shù)。 - 2) 通過調(diào)用CGContextDrawLinearGradient或CGContextDrawRadialGradient并提供上下文琴儿,
CGGradient
對(duì)象段化,繪圖選項(xiàng)以及說明和結(jié)束幾何(軸向漸變點(diǎn)或圓心和徑向漸變的半徑)來繪制漸變。 - 3) 不再需要時(shí)釋放
CGGradient
對(duì)象造成。
位置是CGFloat
值显熏,范圍為0.0到1.0(包括0.0和1.0),用于指定沿梯度軸的標(biāo)準(zhǔn)化距離谜疤。值0.0指定軸的起點(diǎn)佃延,而1.0指定軸的終點(diǎn)。其他值指定距離的比例夷磕,例如距離起點(diǎn)的距離的四分之一為0.25履肃,對(duì)于軸的中間點(diǎn)為0.5。 Quartz至少使用兩個(gè)位置坐桩。如果為位置數(shù)組傳遞NULL
尺棋,則Quartz對(duì)第一個(gè)位置使用0,對(duì)第二個(gè)位置使用1。
每種顏色的顏色分量數(shù)量取決于顏色空間膘螟。對(duì)于屏幕繪圖成福,您將使用RGB顏色空間。由于Quartz使用alpha繪制荆残,因此每個(gè)屏幕顏色都有四個(gè)組件 - 紅色奴艾,綠色,藍(lán)色和alpha内斯。因此蕴潦,對(duì)于屏幕繪圖,您提供的顏色分量數(shù)組中的元素?cái)?shù)必須包含四倍的位置數(shù)俘闯。 Quartz RGBA顏色分量的值可以在0.0到1.0之間變化潭苞,包括0.0和1.0。
Listing 8-1
是一個(gè)創(chuàng)建CGGradient
對(duì)象的代碼片段真朗。在聲明必要的變量之后此疹,代碼設(shè)置位置和必要數(shù)量的顏色分量(對(duì)于此示例,2 X 4 = 8
)遮婶。它創(chuàng)建了一個(gè)通用的RGB色彩空間蝗碎。 (在iOS中,通用RGB顏色空間不可用蹭睡,您的代碼應(yīng)該調(diào)用CGColorSpaceCreateDeviceRGB
衍菱。)然后,它將必要的參數(shù)傳遞給函數(shù)CGGradientCreateWithColorComponents肩豁。您還可以使用函數(shù)CGGradientCreateWithColors,這在您的應(yīng)用程序設(shè)置CGColor對(duì)象時(shí)很方便辫呻。
// Listing 8-1 Creating a CGGradient object
CGGradientRef myGradient;
CGColorSpaceRef myColorspace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 0.5, 0.4, 1.0, // Start color
0.8, 0.8, 0.3, 1.0 }; // End color
myColorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
myGradient = CGGradientCreateWithColorComponents (myColorspace, components,
locations, num_locations);
創(chuàng)建CGGradient對(duì)象后清钥,可以使用它來繪制軸向或線性漸變。 Listing 8-2
是一個(gè)代碼片段放闺,它聲明并設(shè)置線性漸變的起點(diǎn)和終點(diǎn)祟昭,然后繪制漸變。 結(jié)果如圖8-1所示怖侦。 該代碼未顯示如何獲取CGContext
對(duì)象(myContext)
篡悟。
// Listing 8-2 Painting an axial gradient using a CGGradient object
CGPoint myStartPoint, myEndPoint;
myStartPoint.x = 0.0;
myStartPoint.y = 0.0;
myEndPoint.x = 1.0;
myEndPoint.y = 1.0;
CGContextDrawLinearGradient (myContext, myGradient, myStartPoint, myEndPoint, 0);
Listing 8-3
是一個(gè)代碼片段,它使用Listing 8-1
中創(chuàng)建的CGGradient
對(duì)象繪制圖8-9中所示的徑向漸變匾寝。 此示例說明了通過填充純色來擴(kuò)展?jié)u變區(qū)域的結(jié)果搬葬。
// Listing 8-3 Painting a radial gradient using a CGGradient object
CGPoint myStartPoint, myEndPoint;
CGFloat myStartRadius, myEndRadius;
myStartPoint.x = 0.15;
myStartPoint.y = 0.15;
myEndPoint.x = 0.5;
myEndPoint.y = 0.5;
myStartRadius = 0.1;
myEndRadius = 0.25;
CGContextDrawRadialGradient (myContext, myGradient, myStartPoint,
myStartRadius, myEndPoint, myEndRadius,
kCGGradientDrawsAfterEndLocation);
圖8-4中顯示的徑向漸變是使用Listing 8-4
中所示的變量創(chuàng)建的。
// Listing 8-4 The variables used to create a radial gradient by varying alpha
CGPoint myStartPoint, myEndPoint;
CGFloat myStartRadius, myEndRadius;
myStartPoint.x = 0.2;
myStartPoint.y = 0.5;
myEndPoint.x = 0.65;
myEndPoint.y = 0.5;
myStartRadius = 0.1;
myEndRadius = 0.25;
size_t num_locations = 2;
CGFloat locations[2] = { 0, 1.0 };
CGFloat components[8] = { 0.95, 0.3, 0.4, 1.0,
0.95, 0.3, 0.4, 0.1 };
Listing 8-5
顯示了用于創(chuàng)建圖8-10中所示的灰色漸變的變量艳悔,它具有三個(gè)位置急凰。
// Listing 8-5 The variables used to create a gray gradient
size_t num_locations = 3;
CGFloat locations[3] = { 0.0, 0.5, 1.0};
CGFloat components[12] = { 1.0, 1.0, 1.0, 1.0,
0.5, 0.5, 0.5, 1.0,
1.0, 1.0, 1.0, 1.0 };
Using a CGShading Object - 使用CGShading對(duì)象
您可以通過創(chuàng)建調(diào)用函數(shù)CGShadingCreateAxial
或CGShadingCreateRadial
的CGShading
對(duì)象來設(shè)置漸變,并提供以下參數(shù):
- 一個(gè)
CGColorSpace
對(duì)象猜年,描述Quartz在解釋回調(diào)提供的顏色分量值時(shí)使用的顏色空間抡锈。 - 起點(diǎn)和終點(diǎn)疾忍。對(duì)于軸向梯度,這些是軸的起始坐標(biāo)和結(jié)束坐標(biāo)(在用戶空間中)床三。對(duì)于徑向漸變一罩,這些是起始圓和結(jié)束圓的中心坐標(biāo)。用于定義漸變區(qū)域的圓的起點(diǎn)和終點(diǎn)半徑(僅適用于徑向漸變)撇簿。
- 一個(gè)
CGFunction
對(duì)象聂渊,可以通過調(diào)用函數(shù)CGFunctionCreate
獲得,本節(jié)稍后將對(duì)此進(jìn)行討論补疑。此回調(diào)例程必須返回一個(gè)顏色以在特定點(diǎn)繪制歧沪。 - 布爾值,指定是否使用純色填充起點(diǎn)或終點(diǎn)之外的區(qū)域莲组。
您提供給CGShading
創(chuàng)建函數(shù)的CGFunction
對(duì)象包含一個(gè)回調(diào)結(jié)構(gòu)以及Quartz實(shí)現(xiàn)回調(diào)所需的所有信息诊胞。也許設(shè)置CGShading
對(duì)象最棘手的部分是創(chuàng)建CGFunction
對(duì)象。當(dāng)您調(diào)用函數(shù)CGFunctionCreate
時(shí)锹杈,您提供以下內(nèi)容:
- 指向回調(diào)所需數(shù)據(jù)的指針撵孤。
- 回調(diào)的輸入值數(shù)。 Quartz要求你的回調(diào)需要一個(gè)輸入值竭望。
- 一組浮點(diǎn)值邪码。 Quartz只為此數(shù)組中的一個(gè)元素提供回調(diào)。對(duì)于漸變開始時(shí)的顏色咬清,輸入值的范圍可以是0闭专,對(duì)于漸變結(jié)束時(shí)的顏色,輸入值的范圍可以是1旧烧。
- 回調(diào)提供的輸出值的數(shù)量影钉。對(duì)于每個(gè)輸入值,回調(diào)必須為每個(gè)顏色分量提供一個(gè)值掘剪,并為要指定不透明度的alpha值提供平委。顏色組件值由Quartz在您創(chuàng)建的顏色空間中解釋并提供給
CGShading
創(chuàng)建函數(shù)。例如夺谁,如果使用RGB顏色空間廉赔,則提供值4作為輸出值(R,G匾鸥,B和A)的數(shù)量蜡塌。 - 一組浮點(diǎn)值,用于指定每個(gè)顏色分量和alpha值扫腺。
- 一個(gè)回調(diào)數(shù)據(jù)結(jié)構(gòu)岗照,包含結(jié)構(gòu)的版本(將此字段設(shè)置為0),用于生成顏色組件值的回調(diào),以及用于釋放
info
參數(shù)中提供給回調(diào)的數(shù)據(jù)的可選回調(diào)攒至。如果你要將你的回調(diào)命名為myCalculateShadingValues
厚者,它將如下所示:
void myCalculateShadingValues(void * info,const CGFloat * in迫吐,CGFloat * out)
創(chuàng)建CGShading
對(duì)象后库菲,如果需要,可以設(shè)置其他剪輯志膀。然后熙宇,調(diào)用函數(shù)CGContextDrawShading
以使用漸變繪制上下文的剪切區(qū)域。當(dāng)您調(diào)用此函數(shù)時(shí)溉浙,Quartz會(huì)調(diào)用您的回調(diào)以獲取跨越從起點(diǎn)到終點(diǎn)范圍的顏色值烫止。
當(dāng)您不再需要CGShading
對(duì)象時(shí),可以通過調(diào)用函數(shù)CGShadingRelease
來釋放它戳稽。
Painting an Axial Gradient Using a CGShading Object和Painting a Radial Gradient Using a CGShading Object提供有關(guān)編寫使用CGShading
對(duì)象繪制漸變的代碼的分步說明馆蠕。
1. Painting an Axial Gradient Using a CGShading Object - 使用CGShading對(duì)象繪制軸向漸變
軸向和徑向漸變需要您執(zhí)行類似的步驟。 此示例顯示如何使用CGShading
對(duì)象繪制軸向漸變惊奇,在圖形上下文中創(chuàng)建半圓形剪切路徑互躬,然后將漸變繪制到剪切的上下文以實(shí)現(xiàn)圖8-11中所示的輸出。
要繪制圖中所示的軸向漸變颂郎,請(qǐng)按照以下部分中說明的步驟操作:
(1) Set Up a CGFunction Object to Compute Color Values - 設(shè)置CGFunction對(duì)象以計(jì)算顏色值
您可以按照自己喜歡的方式計(jì)算顏色值吼渡,只要您的顏色計(jì)算函數(shù)有三個(gè)參數(shù):
-
void *info
。這是NULL
或指向傳遞給CGShading
創(chuàng)建函數(shù)的數(shù)據(jù)的指針乓序。 -
const CGFloat * in
寺酪。 Quartz將in
數(shù)組傳遞給你的回調(diào)。數(shù)組中的值必須位于為CGFunction
對(duì)象定義的輸入值范圍內(nèi)替劈。對(duì)于此示例房维,輸入范圍是0到1;請(qǐng)參見Listing 8-7
抬纸。 -
CGFloat * out
。你的回調(diào)將out
數(shù)組傳遞給Quartz
耿戚。它包含顏色空間中每個(gè)顏色分量的一個(gè)元素和一個(gè)alpha值湿故。輸出值應(yīng)該在為CGFunction
對(duì)象定義的輸出值范圍內(nèi)。對(duì)于此示例膜蛔,輸出范圍是0到1坛猪;請(qǐng)參見Listing 8-7
。
有關(guān)這些參數(shù)的更多信息皂股,請(qǐng)參閱CGFunctionEvaluateCallback墅茉。
Listing 8-6
顯示了一個(gè)函數(shù),它通過將常量數(shù)組中定義的值乘以輸入值來計(jì)算顏色分量值。因?yàn)檩斎胫档姆秶?到1就斤,所以輸出值的范圍從黑色(對(duì)于RGB悍募,值0,0,0)到通過(1,0,.5)
是紫色色調(diào)洋机。請(qǐng)注意坠宴,最后一個(gè)組件始終設(shè)置為1,因此顏色始終是完全不透明的绷旗。
// Listing 8-6 Computing color component values
static void myCalculateShadingValues (void *info,
const CGFloat *in,
CGFloat *out)
{
CGFloat v;
size_t k, components;
static const CGFloat c[] = {1, 0, .5, 0 };
components = (size_t)info;
v = *in;
for (k = 0; k < components -1; k++)
*out++ = c[k] * v;
*out++ = 1;
}
在編寫回調(diào)以計(jì)算顏色值之后喜鼓,將其打包為CGFunction
對(duì)象的一部分。 它是您在創(chuàng)建CGShading
對(duì)象時(shí)提供給Quartz的CGFunction對(duì)象衔肢。 Listing 8-7
顯示了一個(gè)創(chuàng)建CGFunction對(duì)象的函數(shù)庄岖,該對(duì)象包含Listing 8-6
中的回調(diào)。 列表后面會(huì)顯示每個(gè)編號(hào)行代碼的詳細(xì)說明角骤。
// Listing 8-7 Creating a CGFunction object
static CGFunctionRef myGetFunction (CGColorSpaceRef colorspace)// 1
{
size_t numComponents;
static const CGFloat input_value_range [2] = { 0, 1 };
static const CGFloat output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
static const CGFunctionCallbacks callbacks = { 0,// 2
&myCalculateShadingValues,
NULL };
numComponents = 1 + CGColorSpaceGetNumberOfComponents (colorspace);// 3
return CGFunctionCreate ((void *) numComponents, // 4
1, // 5
input_value_range, // 6
numComponents, // 7
output_value_ranges, // 8
&callbacks);// 9
}
這是代碼的作用:
- 1)將顏色空間作為參數(shù)隅忿。
- 2)聲明一個(gè)回調(diào)結(jié)構(gòu)并用
structure(0)
的版本填充它,指向顏色組件計(jì)算回調(diào)的指針启搂,以及可選釋放函數(shù)的NULL
硼控。 - 3)計(jì)算顏色空間中顏色分量的數(shù)量,并將值遞增1以計(jì)算alpha值胳赌。
- 4)傳遞指向
numComponents
值的指針牢撼。回調(diào)myCalculateShadingValues
使用此值來確定要計(jì)算的組件數(shù)疑苫。 - 5)指定1是回調(diào)的輸入值的數(shù)量熏版。
- 6)提供一個(gè)數(shù)組,指定輸入的有效間隔捍掺。該數(shù)組包含0和1撼短。
- 7)傳遞輸出值的數(shù)量,即顏色分量加上alpha的數(shù)量挺勿。
- 8)提供一個(gè)數(shù)組曲横,指定每個(gè)輸出值的有效間隔。此數(shù)組為每個(gè)組件指定間隔0和1.因?yàn)橛兴膫€(gè)組件不瓶,所以此數(shù)組中有八個(gè)元素禾嫉。
- 9)傳遞指向先前聲明和填充的回調(diào)結(jié)構(gòu)的指針。
(2) Create a CGShading Object for an Axial Gradient - 為軸向漸變創(chuàng)建CGShading對(duì)象
要?jiǎng)?chuàng)建CGShading
對(duì)象蚊丐,可以調(diào)用函數(shù)CGShadingCreateAxial
熙参,如Listing 8-8
所示,傳遞顏色空間麦备,起點(diǎn)和終點(diǎn)孽椰,CGFunction
對(duì)象和布爾值昭娩,該值指定是否填充開始和結(jié)束之外的區(qū)域漸變點(diǎn)。
// Listing 8-8 Creating a CGShading object for an axial gradient
CGPoint startPoint,
endPoint;
CGFunctionRef myFunctionObject;
CGShadingRef myShading;
startPoint = CGPointMake(0,0.5);
endPoint = CGPointMake(1,0.5);
colorspace = CGColorSpaceCreateDeviceRGB();
myFunctionObject = myGetFunction (colorspace);
myShading = CGShadingCreateAxial (colorspace,
startPoint, endPoint,
myFunctionObject,
false, false);
(3) Clip the Context - 裁剪上下文
當(dāng)您繪制漸變時(shí)黍匾,Quartz會(huì)填充當(dāng)前上下文栏渺。 繪制漸變與使用顏色和圖案不同,顏色和圖案用于描邊和填充路徑對(duì)象膀捷。 因此迈嘹,如果希望漸變顯示在特定形狀中,則需要相應(yīng)地剪切上下文全庸。 Listing 8-9
中的代碼在當(dāng)前上下文中添加了一個(gè)半圓秀仲,以便將漸變繪制到該剪輯區(qū)域中,如圖8-11所示壶笼。
如果你仔細(xì)觀察神僵,你會(huì)注意到代碼應(yīng)該產(chǎn)生一個(gè)半圓,而圖中顯示的是半橢圓覆劈。 為什么保礼? 當(dāng)您在A Complete Routine for an Axial Gradient Using a CGShading Object中查看整個(gè)例程時(shí),您將看到上下文也被縮放责语。 稍后會(huì)詳細(xì)介紹炮障。 雖然您可能不需要在應(yīng)用程序中應(yīng)用縮放或剪輯,但Quartz 2D中存在這些和許多其他選項(xiàng)可幫助您實(shí)現(xiàn)有趣的效果坤候。
// Listing 8-9 Adding a semicircle clip to the graphics context
CGContextBeginPath (myContext);
CGContextAddArc (myContext, .5, .5, .3, 0,
my_convert_to_radians (180), 0);
CGContextClosePath (myContext);
CGContextClip (myContext);
(4)Paint the Axial Gradient Using a CGShading Object - 使用CGShading對(duì)象繪制軸向漸變
調(diào)用函數(shù)CGContextDrawShading
以使用CGShading
對(duì)象中指定的顏色漸變填充當(dāng)前上下文:
CGContextDrawShading (myContext, myShading);
(5) Release Objects - 釋放對(duì)象
當(dāng)您不再需要CGShading
對(duì)象時(shí)胁赢,可以調(diào)用函數(shù)CGShadingRelease
。 您還需要釋放CGColorSpace
對(duì)象和CGFunction
對(duì)象白筹,如Listing 8-10
所示智末。
// Listing 8-10 Releasing objects
CGShadingRelease (myShading);
CGColorSpaceRelease (colorspace);
CGFunctionRelease (myFunctionObject);
3. A Complete Routine for an Axial Gradient Using a CGShading Object - 使用CGShading對(duì)象的軸向漸變的完整例程
Listing 8-11
中的代碼顯示了一個(gè)完整的例程,該例程使用Listing 8-7
中設(shè)置的CGFunction
對(duì)象和Listing 8-6
中顯示的回調(diào)來繪制軸向漸變徒河。 列表后面會(huì)顯示每個(gè)編號(hào)行代碼的詳細(xì)說明系馆。
// Listing 8-11 Painting an axial gradient using a CGShading object
void myPaintAxialShading (CGContextRef myContext,// 1
CGRect bounds)
{
CGPoint startPoint,
endPoint;
CGAffineTransform myTransform;
CGFloat width = bounds.size.width;
CGFloat height = bounds.size.height;
startPoint = CGPointMake(0,0.5); // 2
endPoint = CGPointMake(1,0.5);// 3
colorspace = CGColorSpaceCreateDeviceRGB();// 4
myShadingFunction = myGetFunction(colorspace);// 5
shading = CGShadingCreateAxial (colorspace, // 6
startPoint, endPoint,
myShadingFunction,
false, false);
myTransform = CGAffineTransformMakeScale (width, height);// 7
CGContextConcatCTM (myContext, myTransform);// 8
CGContextSaveGState (myContext);// 9
CGContextClipToRect (myContext, CGRectMake(0, 0, 1, 1));// 10
CGContextSetRGBFillColor (myContext, 1, 1, 1, 1);
CGContextFillRect (myContext, CGRectMake(0, 0, 1, 1));
CGContextBeginPath (myContext);// 11
CGContextAddArc (myContext, .5, .5, .3, 0,
my_convert_to_radians (180), 0);
CGContextClosePath (myContext);
CGContextClip (myContext);
CGContextDrawShading (myContext, shading);// 12
CGColorSpaceRelease (colorspace);// 13
CGShadingRelease (shading);
CGFunctionRelease (myShadingFunction);
CGContextRestoreGState (myContext); // 14
}
這是代碼的作用:
- 1)將參數(shù)作為圖形上下文和要繪制的矩形。
- 2)為起點(diǎn)指定一個(gè)值顽照。例程根據(jù)用戶空間計(jì)算值由蘑,該用戶空間從0到1不等。您將稍后為Quartz繪制的窗口縮放空間代兵。您可以將此坐標(biāo)位置視為最左側(cè)的x和距離底部50%的y纵穿。
- 3)為結(jié)束點(diǎn)指定一個(gè)值。您可以將此坐標(biāo)位置視為最右側(cè)的x奢人,y是底部的50%。如您所見淆院,漸變的軸是水平線何乎。
- 4)為設(shè)備RGB創(chuàng)建顏色空間句惯,因?yàn)榇死虒⒗L制到顯示器。
- 5)通過調(diào)用Listing 8-7中所示的例程并傳遞剛剛創(chuàng)建的顏色空間來創(chuàng)建
CGFunction
對(duì)象支救。 - 6)為軸向漸變創(chuàng)建
CGShading
對(duì)象抢野。最后兩個(gè)參數(shù)為false
,表示Quartz不應(yīng)填充起點(diǎn)和終點(diǎn)之外的區(qū)域各墨。 - 7)設(shè)置仿射變換指孤,該變換縮放到用于繪制的窗口的高度和寬度。請(qǐng)注意贬堵,高度不一定等于寬度恃轩。在這個(gè)例子中,因?yàn)閮烧卟幌嗟壤枳觯罱K結(jié)果是橢圓形而不是圓形叉跛。
- 8)將剛剛設(shè)置的轉(zhuǎn)換與傳遞給例程的圖形上下文連接起來。
- 9)保存圖形狀態(tài)蒸殿,以便稍后恢復(fù)此狀態(tài)筷厘。
- 10)設(shè)置剪切區(qū)域。此行和接下來的兩行將上下文剪切為填充白色的矩形宏所。效果是將漸變繪制到具有白色背景的窗口酥艳。
- 11)創(chuàng)建一個(gè)路徑。此行和接下來的三行設(shè)置一個(gè)半圓的圓弧爬骤,并將其作為剪切區(qū)域添加到圖形上下文中充石。效果是將漸變繪制到半個(gè)圓的區(qū)域。但是盖腕,圓圈??將通過窗口的高度和寬度進(jìn)行變換(參見步驟8)赫冬,從而產(chǎn)生繪制為半橢圓的漸變的最終效果。當(dāng)窗口由用戶調(diào)整大小時(shí)溃列,剪裁區(qū)域被調(diào)整大小劲厌。
- 12)如前所述,將漸變繪制到圖形上下文听隐,轉(zhuǎn)換和剪切漸變补鼻。
- 13)釋放對(duì)象。此行和接下來的兩行將釋放您創(chuàng)建的所有對(duì)象雅任。
- 14)將圖形狀態(tài)恢復(fù)為設(shè)置填充背景之前存在的狀態(tài)并剪切為半圈风范。恢復(fù)的狀態(tài)仍然由窗口的寬度和高度轉(zhuǎn)換沪么。
4. Painting a Radial Gradient Using a CGShading Object - 使用CGShading對(duì)象繪制徑向漸變
此示例顯示如何使用CGShading
對(duì)象生成如圖8-12所示的輸出硼婿。
要繪制徑向漸變,請(qǐng)按照以下各節(jié)中說明的步驟操作:
- 1) Set Up a CGFunction Object to Compute Color Values
- 2) Create a CGShading Object for a Radial Gradient
- 3) Paint a Radial Gradient Using a CGShading Object
- 4) Release Objects
(1) Set Up a CGFunction Object to Compute Color Values - 設(shè)置CGFunction對(duì)象以計(jì)算顏色值
寫入函數(shù)以計(jì)算徑向和軸向梯度的顏色值之間沒有區(qū)別禽车。 實(shí)際上寇漫,您可以按照Set Up a CGFunction Object to Compute Color Values設(shè)置軸向漸變刊殉。 Listing 8-12
計(jì)算顏色,使顏色分量正弦變化州胳,周期基于函數(shù)中聲明的頻率值记焊。 圖8-12中顯示的結(jié)果與圖8-11中顯示的顏色完全不同。 盡管顏色輸出存在差異栓撞,但Listing 8-12
中的代碼與Listing 8-6
類似遍膜,因?yàn)槊總€(gè)函數(shù)都遵循相同的原型。 每個(gè)函數(shù)接受一個(gè)輸入值并計(jì)算N個(gè)值瓤湘,一個(gè)用于顏色空間的每個(gè)顏色分量加上一個(gè)alpha值瓢颅。
// Listing 8-12 Computing color component values
static void myCalculateShadingValues (void *info,
const CGFloat *in,
CGFloat *out)
{
size_t k, components;
double frequency[4] = { 55, 220, 110, 0 };
components = (size_t)info;
for (k = 0; k < components - 1; k++)
*out++ = (1 + sin(*in * frequency[k]))/2;
*out++ = 1; // alpha
}
回想一下,在編寫顏色計(jì)算函數(shù)之后岭粤,需要?jiǎng)?chuàng)建一個(gè)CGFunction對(duì)象惜索,如Set Up a CGFunction Object to Compute Color Values中的軸向值所述。
(2) Create a CGShading Object for a Radial Gradient - 為徑向漸變創(chuàng)建CGShading對(duì)象
要?jiǎng)?chuàng)建CGShading
對(duì)象或徑向漸變剃浇,可以調(diào)用函數(shù)CGShadingCreateRadial
巾兆,如Listing 8-13所示,傳遞顏色空間虎囚,起點(diǎn)和終點(diǎn)角塑,開始和結(jié)束半徑,CGFunction
對(duì)象和布爾值淘讥,以指定是否填充漸變的起點(diǎn)和終點(diǎn)之外的區(qū)域圃伶。
// Listing 8-13 Creating a CGShading object for a radial gradient
CGPoint startPoint, endPoint;
CGFloat startRadius, endRadius;
startPoint = CGPointMake(0.25,0.3);
startRadius = .1;
endPoint = CGPointMake(.7,0.7);
endRadius = .25;
colorspace = CGColorSpaceCreateDeviceRGB();
myShadingFunction = myGetFunction (colorspace);
CGShadingCreateRadial (colorspace,
startPoint,
startRadius,
endPoint,
endRadius,
myShadingFunction,
false,
false);
(3) Paint a Radial Gradient Using a CGShading Object - 使用CGShading對(duì)象繪制徑向漸變
調(diào)用函數(shù)CGContextDrawShading
使用CGShading
對(duì)象中指定的指定顏色漸變填充當(dāng)前上下文。
CGContextDrawShading(myContext蒲列,shading);
請(qǐng)注意窒朋,無論漸變是軸向還是徑向最蕾,都使用相同的函數(shù)繪制漸變秸抚。
(4) Release Objects - 釋放對(duì)象
當(dāng)您不再需要CGShading
對(duì)象時(shí)健民,可以調(diào)用函數(shù)CGShadingRelease
喘先。 您還需要釋放CGColorSpace
對(duì)象和CGFunction
對(duì)象,如Listing 8-14
所示敷钾。
// Listing 8-14 Code that releases objects
CGShadingRelease (myShading);
CGColorSpaceRelease (colorspace);
CGFunctionRelease (myFunctionObject);
5. A Complete Routine for Painting a Radial Gradient Using a CGShading Object - 使用CGShading對(duì)象繪制徑向漸變的完整例程
Listing 8-15
中的代碼顯示了一個(gè)完整的例程这敬,它使用Listing 8-7
中設(shè)置的CGFunction對(duì)象和Listing 8-12
中顯示的回調(diào)繪制徑向漸變展辞。 列表后面會(huì)顯示每個(gè)編號(hào)行代碼的詳細(xì)說明铅鲤。
// Listing 8-15 A routine that paints a radial gradient using a CGShading object
void myPaintRadialShading (CGContextRef myContext,// 1
CGRect bounds);
{
CGPoint startPoint,
endPoint;
CGFloat startRadius,
endRadius;
CGAffineTransform myTransform;
CGFloat width = bounds.size.width;
CGFloat height = bounds.size.height;
startPoint = CGPointMake(0.25,0.3); // 2
startRadius = .1; // 3
endPoint = CGPointMake(.7,0.7); // 4
endRadius = .25; // 5
colorspace = CGColorSpaceCreateDeviceRGB(); // 6
myShadingFunction = myGetFunction (colorspace); // 7
shading = CGShadingCreateRadial (colorspace, // 8
startPoint, startRadius,
endPoint, endRadius,
myShadingFunction,
false, false);
myTransform = CGAffineTransformMakeScale (width, height); // 9
CGContextConcatCTM (myContext, myTransform); // 10
CGContextSaveGState (myContext); // 11
CGContextClipToRect (myContext, CGRectMake(0, 0, 1, 1)); // 12
CGContextSetRGBFillColor (myContext, 1, 1, 1, 1);
CGContextFillRect (myContext, CGRectMake(0, 0, 1, 1));
CGContextDrawShading (myContext, shading); // 13
CGColorSpaceRelease (colorspace); // 14
CGShadingRelease (shading);
CGFunctionRelease (myShadingFunction);
CGContextRestoreGState (myContext); // 15
}
這是代碼的作用:
- 1)將參數(shù)作為圖形上下文和要繪制的矩形划提。
- 2)為起始圓的中心指定一個(gè)值。例程根據(jù)用戶空間計(jì)算值邢享,該用戶空間從0到1不等鹏往。您將稍后為Quartz繪制的窗口縮放空間。您可以將- 此坐標(biāo)位置視為左側(cè)25%處的x和底部30%處的y骇塘。
- 3)指定起始圓的半徑掸犬。您可以將其視為用戶空間寬度的10%袜漩。
- 4)為結(jié)束圓的中心指定一個(gè)值。您可以將此坐標(biāo)位置視為左側(cè)70%的x和底部70%的y湾碎。
- 5)指定結(jié)束圓的半徑。您可以將其視為用戶空間寬度的25%奠货。結(jié)束圓圈將大于起始圓圈介褥。圓錐形狀將從左向右定向,向上傾斜递惋。
- 6)為設(shè)備RGB創(chuàng)建顏色空間柔滔,因?yàn)榇死虒⒗L制到顯示器。
- 7)通過調(diào)用Listing 8-7中所示的例程并傳遞剛剛創(chuàng)建的顏色空間來創(chuàng)建
CGFunctionObject
萍虽。但是睛廊,請(qǐng)記住,您將使用Listing 8-12中所示的顏色計(jì)算函數(shù)杉编。 - 8)為徑向漸變創(chuàng)建
CGShading
對(duì)象超全。最后兩個(gè)參數(shù)為false
,表示Quartz不應(yīng)填充漸變起點(diǎn)和終點(diǎn)之外的區(qū)域邓馒。 - 9)設(shè)置仿射變換嘶朱,該變換縮放到用于繪制的窗口的高度和寬度。請(qǐng)注意光酣,高度不一定等于寬度疏遏。實(shí)際上,只要用戶調(diào)整窗口大小救军,轉(zhuǎn)換就會(huì)改變财异。
- 10)將剛剛設(shè)置的轉(zhuǎn)換與傳遞給例程的圖形上下文連接起來。
- 11)保存圖形狀態(tài)唱遭,以便稍后恢復(fù)此狀態(tài)戳寸。
- 12)設(shè)置剪切區(qū)域。此行和接下來的兩行將上下文剪切為填充白色的矩形胆萧。效果是將漸變繪制到具有白色背景的窗口庆揩。
- 13)如前所述,將漸變繪制到圖形上下文轉(zhuǎn)換漸變跌穗。
- 14)釋放對(duì)象订晌。此行和接下來的兩行將釋放您創(chuàng)建的所有對(duì)象。
- 15)將圖形狀態(tài)恢復(fù)為設(shè)置填充背景之前存在的狀態(tài)蚌吸⌒獠Γ恢復(fù)的狀態(tài)仍然由窗口的寬度和高度轉(zhuǎn)換。
See Also - 同可參考
-
CGGradient Reference描述了創(chuàng)建
CGGradient
對(duì)象的函數(shù)羹唠。 -
CGShading Reference描述了創(chuàng)建
CGShading
對(duì)象的函數(shù)奕枢。 -
CGFunction Reference描述了計(jì)算
CGShading
對(duì)象的漸變顏色所需的函數(shù)娄昆。 -
CGContext Reference描述了使用
CGGradient
和CGShading
對(duì)象繪制到上下文的函數(shù)。
后記
本篇主要講述了漸變缝彬,感興趣的給個(gè)贊或者關(guān)注~~~