Quartz 2D編程指南之八:漸變

本文轉(zhuǎn)載自:http://southpeak.github.io/2014/12/10/quartz2d-8/

Quartz提供了兩個(gè)不透明數(shù)據(jù)odgago創(chuàng)建漸變:CGShadingRef和CGGradientRef。我們可以使用任何一個(gè)來(lái)創(chuàng)建軸向(axial)或徑向(radial)漸變。一個(gè)漸變是從一個(gè)顏色到另外一種顏色的填充。

一個(gè)軸向漸變(也稱為線性漸變)沿著由兩個(gè)端點(diǎn)連接的軸線漸變。所有位于垂直于軸線的某條線上的點(diǎn)都具有相同的顏色值。

一個(gè)徑向漸變也是沿著兩個(gè)端點(diǎn)連接的軸線漸變,不過路徑通常由兩個(gè)圓來(lái)定義。

本章提供了一些我們使用Quartz能夠創(chuàng)建的軸向和徑向漸變的類型的例子,并比較繪制漸變的兩種方法,然后演示了如何使用每種不透明數(shù)據(jù)類型來(lái)創(chuàng)建漸變。

軸向和徑向漸變實(shí)例

Quartz函數(shù)提供了一個(gè)豐富的功能來(lái)創(chuàng)建漸變效果。這一部分顯示了一些我們能達(dá)到的效果。圖8-1中的軸向漸變由橙色向黃色漸變。在這個(gè)例子中,漸變軸相對(duì)于原點(diǎn)傾斜了45度角。

Figure 8-1 An axial gradient along a 45 degree axis

Quartz也允許我們指定一系列的顏色和位置值,以沿著軸來(lái)創(chuàng)建更復(fù)雜的軸向漸變,如圖8-2所示。起始點(diǎn)的顏色值是紅色,結(jié)束點(diǎn)的顏色是紫羅蘭色。同時(shí),在軸上有五個(gè)位置,它們的顏色值分別被設(shè)置為橙、黃、綠、藍(lán)和靛藍(lán)。我們可以把它看成沿著同一軸線的六段連續(xù)的線性漸變。雖然這里的軸線與圖8-1是一樣的,但這不是必須的。軸線的角度由我們提供的兩個(gè)端點(diǎn)定義。

Figure 8-2 An axial gradient created with seven locations and colors

圖8-3顯示了一個(gè)徑向漸變,它從一個(gè)小的明亮的紅色圓漸變到一個(gè)大小黑色的圓。

Figure 8-3 A radial gradient that varies between two circles

使用Quartz,我們不局限于創(chuàng)建顏色值改變的漸變;我們可以只修改alpha值,或者創(chuàng)建alpha值與其它顏色組件一起改變的漸變。圖8-4顯示了一個(gè)漸變,其紅、綠、藍(lán)組件的值是不變的,但alpha值從1.0漸變到0.1。

注意:如果我們使用alpha值來(lái)改變一個(gè)漸變,則在繪制一個(gè)PDF內(nèi)容時(shí)我們不能捕獲這個(gè)漸變。因此,這樣的漸變無(wú)法打印。如果需要繪制一個(gè)漸變到PDF,則需要讓alpha值為1.0。

Figure 8-4 A radial gradient created by varying only the alpha component

我們可以把一個(gè)圓放置到一個(gè)徑向漸變中來(lái)創(chuàng)建各種形狀。如果一個(gè)圓是另一個(gè)的一部分或者完全在另一個(gè)的外面,則Quartz創(chuàng)建了圓錐和一個(gè)圓柱。徑向漸變的一個(gè)通常用法就是創(chuàng)建一個(gè)球體陰影,如圖8-5所示。在這種情況下,一個(gè)單一的點(diǎn)(半徑為0的圓)位于一個(gè)大圓以內(nèi)。

Figure 8-5 A radial gradient that varies between a point and a circle

我們可以像圖8-6一樣通過內(nèi)嵌幾個(gè)徑向漸變來(lái)創(chuàng)建更復(fù)雜的效果。它使用同心圓來(lái)創(chuàng)建圖形中的各環(huán)形部分。

Figure 8-6 Nested radial gradients

CGShading和CGGradient對(duì)象的對(duì)比

我們有兩個(gè)對(duì)象類型用于創(chuàng)建漸變,你可能想知道哪一個(gè)更好用。本節(jié)就來(lái)回答這個(gè)問題。

CGShadingRef這個(gè)不透明數(shù)據(jù)類型給我們更多的控制權(quán),以確定如何計(jì)算每個(gè)端點(diǎn)的顏色。在我們創(chuàng)建CGShading對(duì)象之前,我們必須創(chuàng)建一個(gè)CGFunction對(duì)象(CGFunctionRef),這個(gè)對(duì)象定義了一個(gè)用于計(jì)算漸變顏色的函數(shù)。寫一個(gè)自定義的函數(shù)讓我們能夠創(chuàng)建平滑的漸變,如圖8-3,8-3和8-5及更多非傳統(tǒng)的效果,如圖8-12所示。

當(dāng)創(chuàng)建一個(gè)CGShading對(duì)象時(shí),我們指定其是軸向還是徑向。除了計(jì)算函數(shù)外,我們還需要提供一個(gè)顏色空間、起始點(diǎn)和結(jié)束點(diǎn)或者是半徑,這取決于是繪制軸向還是徑向漸變。在繪制時(shí),我們只是簡(jiǎn)單地傳遞CGShading對(duì)象及繪制上下文給CGContextDrawShading函數(shù)。Quartz為漸變上的每個(gè)點(diǎn)調(diào)用漸變計(jì)算函數(shù)。

一個(gè)CGGradient對(duì)象是CGShading對(duì)象的子集,其更易于使用。CGGradientRef不透明類型易于作用,因?yàn)镼uartz在漸變的每一個(gè)頂點(diǎn)上計(jì)算顏色值。我們不需要提供一個(gè)漸變計(jì)算函數(shù)。當(dāng)創(chuàng)建一個(gè)漸變對(duì)象時(shí),我們提供一個(gè)位置和顏色的數(shù)組。Quartz使用對(duì)應(yīng)的顏色值來(lái)計(jì)算每個(gè)梯度的漸變,。我們可以使用單一的起始與結(jié)束點(diǎn)來(lái)設(shè)置一個(gè)漸變對(duì)象,如圖8-1所示,或者提供一組端點(diǎn)來(lái)創(chuàng)建一個(gè)類似于圖8-2的的效果。使用CGShading對(duì)象可以提供多于兩個(gè)位置的能力。

當(dāng)我們創(chuàng)建一個(gè)CGGradient對(duì)象時(shí),我們需要設(shè)置一個(gè)顏色空間、位置、和每個(gè)位置對(duì)應(yīng)的顏色值。當(dāng)使用一個(gè)漸變對(duì)象繪制上下文時(shí),我們指定Quartz是繪制一個(gè)軸向還是徑向漸變。在繪制時(shí),我們指定開始結(jié)束點(diǎn)或半徑,這取決于我們是繪制軸向還是徑向漸變。而CGShading的幾何形狀是在創(chuàng)建時(shí)定義的,而不是繪制時(shí)。

表8-1總結(jié)了兩種不透明數(shù)據(jù)類型之間的區(qū)別。

擴(kuò)展?jié)u變端點(diǎn)外部的顏色

當(dāng)我們創(chuàng)建一個(gè)漸變時(shí),我們可以選擇使用純色來(lái)填充漸變端點(diǎn)外部的空間。Quartz使用使用漸變邊界上的顏色作為填充顏色。我們可以擴(kuò)展?jié)u變起點(diǎn)、終點(diǎn)或兩端的顏色。我們可以擴(kuò)展使用CGShading對(duì)象或CGGradient對(duì)象創(chuàng)建的軸向或徑向漸變。

圖8-7演示了一個(gè)軸向漸變,它擴(kuò)展了起點(diǎn)和終點(diǎn)兩側(cè)的區(qū)域。圖片中的線段顯示了漸變的軸線。我們可以看到,填充顏色與起點(diǎn)和終點(diǎn)的顏色是對(duì)應(yīng)的。

Figure 8-7 Extending an axial gradient

圖8-8對(duì)比了一個(gè)未使用擴(kuò)展的徑向漸變和一個(gè)在起點(diǎn)和終點(diǎn)兩側(cè)使用擴(kuò)展的徑向漸變。Quartz獲取了起點(diǎn)和終點(diǎn)的顏色值,并使用這邊純色值來(lái)擴(kuò)展立面。

Figure 8-8 Extending a radial gradient

使用CGGradient對(duì)象

一個(gè)CGGradient對(duì)象是一個(gè)漸變的抽象定義–它簡(jiǎn)單地指定了顏色值和位置,但沒有指定幾何形狀。我們可以在軸向和徑向幾何形狀中使用這個(gè)對(duì)象。作為一個(gè)抽象定義,CGGradient對(duì)象可能比CGShading對(duì)象更容易重用。沒有將幾何形狀存儲(chǔ)在CGGradient對(duì)象中,這樣允許我們使用相同的顏色方案來(lái)繪制不同的幾何圖形,而不需要為多個(gè)圖形創(chuàng)建多個(gè)CGGradient對(duì)象。

因?yàn)镼uartz為我們計(jì)算漸變,使用一個(gè)CGGradient對(duì)象來(lái)創(chuàng)建和繪制一個(gè)漸變則更直接,只需要以下幾步:

創(chuàng)建一個(gè)CGGradient對(duì)象,提供一個(gè)顏色空間,一個(gè)飽含兩個(gè)或更多顏色組件的數(shù)組,一個(gè)包含兩個(gè)或多個(gè)位置的數(shù)組,和兩個(gè)數(shù)組中元素的個(gè)數(shù)。

調(diào)用CGContextDrawLinearGradient或CGContextDrawRadialGradient函數(shù)并提供一個(gè)上下文、一個(gè)CGGradient對(duì)象、繪制選項(xiàng)和開始結(jié)束幾何圖形來(lái)繪制漸變。

當(dāng)不再需要時(shí)釋放CGGradient對(duì)象。

一個(gè)位置是一個(gè)值區(qū)間在0.0到1.0之間的CGFloat值,它指定了沿著漸變的軸線的標(biāo)準(zhǔn)化距離。值0.0指定的軸線的起點(diǎn),1.0指定了軸線的終點(diǎn)。其它的值指定了一個(gè)距離的比例。最低限度情況下,Quartz使用兩個(gè)位置值。如果我們傳遞NULL值作為位置數(shù)組參數(shù),則Quartz使用0作為第一個(gè)位置,1作為第二個(gè)位置。

每個(gè)顏色的顏色組件的數(shù)目取決于顏色空間。對(duì)于離屏繪制,我們使用一個(gè)RGB顏色空間。因?yàn)镼uartz使用alpha來(lái)繪制,每個(gè)離屏顏色都有四個(gè)組件–紅、綠、藍(lán)和alpha。所以,對(duì)于離屏繪制,我們提供的顏色組件數(shù)組的元素的數(shù)目必須是位置數(shù)目的4倍。Quartz的RGBA顏色組件可以在0.0到1.0之間改變。

代碼清單8-1是創(chuàng)建一個(gè)CGGradient對(duì)象的代碼片斷。在聲明了必須的變量后,代碼設(shè)置了位置和顏色組件數(shù)組。然后創(chuàng)建了一個(gè)通用的RGB顏色空間。(在iOS中,不管RGB顏色空間是否可用,我們都應(yīng)該調(diào)用CGColorSpaceCreateDeviceRGB)。然后,它傳遞必要的參數(shù)到CGGradientCreateWithColorComponents函數(shù)。我們同樣可以使用CGGradientCreateWithColors,如果我們的程序設(shè)置了CGColor對(duì)象,這是一種便捷的方法。

Listing 8-1 Creating a CGGradient object

CGGradientRef myGradient;

CGColorSpaceRef myColorspace;

size_tnum_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ì)象后,我們可以使用它來(lái)繪制一個(gè)軸向或線性漸變。代碼清單8-2聲明并設(shè)置了線性漸變的起始點(diǎn)然后繪制漸變。圖8-1顯示了結(jié)果。代碼沒有演示如何獲取CGContext對(duì)象。

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);

代碼清單8-3使用代碼清單8-1中創(chuàng)建的CGGradient對(duì)象來(lái)繪制圖8-9中徑向漸變。這個(gè)例子同時(shí)也演示了使用純色來(lái)填充漸變的擴(kuò)展區(qū)域。

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);

Figure 8-9 A radial gradient painted using a CGGradient object

圖8-4中的徑向漸變使用代碼清單8-4中的變量來(lái)創(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_tnum_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};

代碼清單8-5顯示了用于創(chuàng)建圖8-10中的灰色漸變的變量,其中有3個(gè)位置。

Listing 8-5 The variables used to create a gray gradient

size_tnum_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};

Figure 8-10 An axial gradient with three locations

使用CGShading對(duì)象

我們通過調(diào)用函數(shù)CGShadingCreateAxial或CGShadingCreateRadial創(chuàng)建一個(gè)CGShading對(duì)象來(lái)設(shè)置一個(gè)漸變,調(diào)用這些函數(shù)需要提供以下參數(shù):

CGColorSpace對(duì)象:顏色空間

起始點(diǎn)和終點(diǎn)。對(duì)于軸向漸變,有軸線的起始點(diǎn)和終點(diǎn)的坐標(biāo)。對(duì)于徑向漸變,有起始圓和終點(diǎn)圓中心的坐標(biāo)。

用于定義漸變區(qū)域的圓的起始半徑與終止半徑。

一個(gè)CGFunction對(duì)象,可以通過CGFunctionCreate函數(shù)來(lái)獲取。這個(gè)回調(diào)例程必須返回繪制到特定點(diǎn)的顏色值。

一個(gè)布爾值,用于指定是否使用純色來(lái)繪制起始點(diǎn)與終點(diǎn)的擴(kuò)展區(qū)域。

我們提供給CGShading創(chuàng)建函數(shù)的CGFunction對(duì)象包含一個(gè)回調(diào)結(jié)構(gòu)體,及Quartz需要實(shí)現(xiàn)這個(gè)回調(diào)的所有信息。也許設(shè)置CGShasing對(duì)象的最棘手的部分是創(chuàng)建CGFunction對(duì)象。當(dāng)我們調(diào)用CGFunctionCreate函數(shù)時(shí),我們提供以下參數(shù):

指向回調(diào)所需要的數(shù)據(jù)的指針

回調(diào)的輸入值的個(gè)數(shù)。Quartz要求回調(diào)攜帶一個(gè)輸入值。

一個(gè)浮點(diǎn)數(shù)的數(shù)組。Quartz只會(huì)提供數(shù)組中的一個(gè)元素給回調(diào)函數(shù)。一個(gè)轉(zhuǎn)入值的范圍是0(漸變的開始點(diǎn)的顏色)到1(漸變的結(jié)束點(diǎn)的顏色)。

回調(diào)提供的輸出值的數(shù)目。對(duì)于每一個(gè)輸入值,我們的回調(diào)必須為每個(gè)顏色組件提供一個(gè)值,以及一個(gè)alpha值來(lái)指定透明度。顏色組件值由Quartz提供的顏色空間來(lái)解釋,并會(huì)提供給CGShading創(chuàng)建函數(shù)。例如,如果我們使用RGB顏色空間,則我們提供值4作為輸出值(R,G,B,A)的數(shù)目。

一個(gè)浮點(diǎn)數(shù)的數(shù)組,用于指定每個(gè)顏色組件的值及alpha值。

一個(gè)回調(diào)數(shù)據(jù)結(jié)構(gòu),包含結(jié)構(gòu)體的版本(設(shè)置為0)、生成顏色組件值的回調(diào)、一個(gè)可選的用于釋放回調(diào)中info參數(shù)表示的數(shù)據(jù)。該回調(diào)類似于以下格式:

void myCalculateShadingValues(void*info,constCGFloat *in, CGFloat *out)

在創(chuàng)建CGShading對(duì)象后,如果需要我們可以設(shè)置額外的裁減操作。然后調(diào)用CGContextDrawShading函數(shù)來(lái)使用漸變來(lái)繪制上下文的裁減區(qū)域。當(dāng)調(diào)用這個(gè)函數(shù)時(shí),Quartz調(diào)用回調(diào)函數(shù)來(lái)獲取從起點(diǎn)到終點(diǎn)這個(gè)范圍內(nèi)的顏色值。

當(dāng)不再需要CGShading對(duì)象時(shí),我們調(diào)用CGShadingRelease來(lái)釋放它。

下面我們將一步步地通過代碼來(lái)看看如何使用CGShading對(duì)象來(lái)繪制漸變。

使用CGShading對(duì)象繪制一個(gè)軸向漸變

繪制軸向和徑向漸變的步驟是差不多的。這個(gè)例子演示了如何使用一個(gè)CGShading對(duì)象來(lái)繪制一個(gè)軸向漸變,并在圖形上下文中繪制一個(gè)半圓形的裁減路徑,然后將漸變繪制到裁減區(qū)域來(lái)達(dá)到圖8-11的效果。

Figure 8-11 An axial gradient that is clipped and painted

為了繪制圖中的軸向漸變,需要按以下步驟來(lái)處理:

設(shè)置CGFunction對(duì)象來(lái)計(jì)算顏色值

創(chuàng)建軸向漸變的CGShading對(duì)象

裁減上下文

使用CGShading對(duì)象來(lái)繪制軸向漸變

釋放對(duì)象

設(shè)置CGFunction對(duì)象來(lái)計(jì)算顏色值

我們可以以我們想要的方式來(lái)計(jì)算顏色值,我們的顏色計(jì)算函數(shù)包含以下三個(gè)參數(shù):

void *info:這個(gè)值可以為NULL或者是一個(gè)指向傳遞給CGShading創(chuàng)建函數(shù)的數(shù)據(jù)。

const CGFloat *in:Quartz傳遞in數(shù)組給回調(diào)。數(shù)組中的值必須在為CGFunction對(duì)象定義的輸入值范圍內(nèi)。例如,輸入范圍是0到1;看代碼清單8-7

CGFloat *out:我們的回調(diào)函數(shù)傳遞out數(shù)組給Quartz。它包含用于顏色空間中每個(gè)顏色組件的元素及一個(gè)alpha值。輸出值應(yīng)該在CGFunction對(duì)象中定義的輸出值的范圍內(nèi),例如,輸出范圍是0到1;看代碼清單8-7。

更多關(guān)于參數(shù)的信息可以查看CGFunctionEvaluateCallback。

代碼清單8-6演示了一個(gè)函數(shù),它通過將一個(gè)常數(shù)數(shù)組中的值乘以輸入值來(lái)計(jì)算顏色組件值。因?yàn)檩斎胫翟?到1之間,所以輸入值位于黑色(對(duì)于RGB來(lái)說值為0, 0, 0)和紫色(1, 0, 0.5)之間。注意最后一個(gè)組件通常設(shè)置為1,表示顏色總是完全不透明的。

Listing 8-6 Computing color component values

static void myCalculateShadingValues(void*info,const CGFloat *in,CGFloat *out){

CGFloat v;

size_tk, components;

staticconstCGFloat 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ì)象的一部分。代碼清單顯示了一個(gè)函數(shù),它創(chuàng)建了一個(gè)包含代碼清單8-6中的回調(diào)函數(shù)的CGFunction對(duì)象。

Listing 8-7 Creating a CGFunction object

static CGFunctionRefmyGetFunction(CGColorSpaceRef colorspace){

size_tnumComponents;

staticconstCGFloat input_value_range [2] = {0,1};

staticconstCGFloat output_value_ranges [8] = {0,1,0,1,0,1,0,1};

staticconstCGFunctionCallbacks callbacks = {0,

&myCalculateShadingValues,

NULL};

numComponents =1+ CGColorSpaceGetNumberOfComponents (colorspace);

returnCGFunctionCreate ((void*) numComponents,

1,

input_value_range,

numComponents,

output_value_ranges,

&callbacks);

}

創(chuàng)建一個(gè)軸向漸變的CGShading對(duì)象

為了創(chuàng)建一個(gè)CGShading對(duì)象,我們調(diào)用CGShadingCreateAxial函數(shù),如代碼清單8-8所示。我們傳遞一個(gè)顏色空間,開始點(diǎn)和結(jié)束點(diǎn),一個(gè)CGFunction對(duì)象,和一個(gè)用于指定是否填充漸變的開始點(diǎn)和結(jié)束點(diǎn)擴(kuò)展的布爾值。

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);

裁減上下文

當(dāng)繪制一個(gè)漸變時(shí),Quartz填充當(dāng)前上下文。繪制一個(gè)漸變與操作顏色和模式不同,后者是用于描邊或填充一個(gè)路徑對(duì)象。因此,如果要我們的漸變出現(xiàn)在一個(gè)特定形狀中,我們需要裁減上下文。代碼清單8-9的代碼添加了一個(gè)半圓形到當(dāng)前上下文,以便漸變繪制到這個(gè)裁減區(qū)域,如圖8-11。

如果我們仔細(xì)看,會(huì)發(fā)現(xiàn)代碼繪制的是一個(gè)半圓,而圖中顯示的是一個(gè)半橢圓形。為什么呢?我們會(huì)看到,當(dāng)我們查看后面完整的繪制代碼時(shí),上下文被縮放了。稍后會(huì)詳細(xì)說明。雖然我們不需要使用縮放或裁減,這些在Quartz 2D中的選項(xiàng)可以幫助我們達(dá)到有趣的效果。

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);

使用CGShading對(duì)象來(lái)繪制軸向漸變

調(diào)用函數(shù)CGContextDrawShading使用CGShading對(duì)象為指定的顏色漸變來(lái)填充當(dāng)前上下文:

CGContextDrawShading (myContext, myShading);

釋放對(duì)象

當(dāng)我們不再需要CGShading對(duì)象時(shí),可以調(diào)用函數(shù)CGShadingRelease來(lái)釋放它。我們需要同時(shí)釋放CGColorSpace對(duì)象和CGFunction對(duì)象,如代碼清單8-10所示:

Listing 8-10 Releasing objects

CGShadingRelease (myShading);

CGColorSpaceRelease (colorspace);

CGFunctionRelease (myFunctionObject);

使用CGShading對(duì)象繪制軸向漸變的完整例程

代碼清單8-11顯示了繪制一個(gè)軸向漸變的完整例程,使用8-7中的CGFunction對(duì)象和8-6中的回調(diào)函數(shù)。

Listing 8-11 Painting an axial gradient using a CGShading object

void myPaintAxialShading(CGContextRef myContext,CGRect bounds){

CGPoint? ? startPoint,

endPoint;

CGAffineTransform myTransform;

CGFloat width = bounds.size.width;

CGFloat height = bounds.size.height;

startPoint = CGPointMake(0,0.5);

endPoint = CGPointMake(1,0.5);

colorspace = CGColorSpaceCreateDeviceRGB();

myShadingFunction = myGetFunction(colorspace);

shading = CGShadingCreateAxial (colorspace,

startPoint, endPoint,

myShadingFunction,

false,false);

myTransform = CGAffineTransformMakeScale (width, height);

CGContextConcatCTM (myContext, myTransform);

CGContextSaveGState (myContext);

CGContextClipToRect (myContext, CGRectMake(0,0,1,1));

CGContextSetRGBFillColor (myContext,1,1,1,1);

CGContextFillRect (myContext, CGRectMake(0,0,1,1));

CGContextBeginPath (myContext);

CGContextAddArc (myContext,.5,.5,.3,0,

my_convert_to_radians (180),0);

CGContextClosePath (myContext);

CGContextClip (myContext);

CGContextDrawShading (myContext, shading);

CGColorSpaceRelease (colorspace);

CGShadingRelease (shading);

CGFunctionRelease (myShadingFunction);

CGContextRestoreGState (myContext);

}

使用CGShading對(duì)象繪制一個(gè)徑向漸變

這個(gè)例子演示了如何使用CGShading對(duì)象來(lái)生成如圖8-12所示的輸出

Figure 8-12 A radial gradient created using a CGShading object

為了繪制一個(gè)徑向漸變,我們需要按以下步驟來(lái)處理:

設(shè)置CGFunction對(duì)象來(lái)計(jì)算顏色值

創(chuàng)建徑向漸變的CGShading對(duì)象

使用CGShading對(duì)象來(lái)繪制徑向漸變

釋放對(duì)象

設(shè)置CGFunction對(duì)象來(lái)計(jì)算顏色值

計(jì)算徑向漸變和軸向漸變顏色值的函數(shù)沒有什么區(qū)別。事實(shí)上,我們可以依照上面的軸向的”設(shè)置CGFunction對(duì)象來(lái)計(jì)算顏色值”。代碼清單8-12用于計(jì)算顏色,使用顏色按正弦變化。圖8-12與圖8-11的結(jié)果非常不同。雖然顏色輸出值不同,代碼清單8-12的代碼與8-6中的函數(shù)遵循相同的原型。每個(gè)函數(shù)獲取一個(gè)輸入值并計(jì)算N個(gè)值,即顏色空間的每個(gè)顏色組件加一個(gè)alpha值。

Listing 8-12 Computing color component values

static void myCalculateShadingValues(void*info,

constCGFloat *in,

CGFloat *out)

{

size_tk, components;

doublefrequency[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ù)后調(diào)用它,我們需要?jiǎng)?chuàng)建一個(gè)CGFunction對(duì)象,如在軸向中”設(shè)置CGFunction對(duì)象來(lái)計(jì)算顏色值”所描述的一樣。

創(chuàng)建徑向漸變的CGShading對(duì)象

為了創(chuàng)建一個(gè)CGShading對(duì)象或者一個(gè)徑向漸變,我們調(diào)用CGShadingCreateRadial函數(shù),如代碼清單8-13所求,傳遞一個(gè)顏色空間、開始點(diǎn)和結(jié)束點(diǎn),開始半徑和結(jié)束半徑,一個(gè)CGFunction對(duì)象,和一個(gè)用于指定是否填充漸變的開始點(diǎn)和結(jié)束點(diǎn)擴(kuò)展的布爾值。

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);

使用CGShading對(duì)象來(lái)繪制徑向漸變

調(diào)用函數(shù)CGContextDrawShading使用CGShading對(duì)象為指定的顏色漸變來(lái)填充當(dāng)前上下文:

CGContextDrawShading (myContext, myShading);

注意我們使用相同的函數(shù)來(lái)繪制漸變,而不管它是軸向還是徑向。

釋放對(duì)象

當(dāng)我們不再需要CGShading對(duì)象時(shí),可以調(diào)用函數(shù)CGShadingRelease來(lái)釋放它。我們需要同時(shí)釋放CGColorSpace對(duì)象和CGFunction對(duì)象,如代碼清單8-14所示:

Listing 8-10 Releasing objects

CGShadingRelease (myShading);

CGColorSpaceRelease (colorspace);

CGFunctionRelease (myFunctionObject);

使用CGShading對(duì)象繪制徑向漸變的完整例程

代碼清單8-15顯示了繪制一個(gè)軸徑向漸變的完整例程,使用8-7中的CGFunction對(duì)象和8-12中的回調(diào)函數(shù)。

Listing 8-15 A routine that paints a radial gradient using a CGShading object

void myPaintRadialShading(CGContextRef myContext,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);

startRadius =.1;

endPoint = CGPointMake(.7,0.7);

endRadius =.25;

colorspace = CGColorSpaceCreateDeviceRGB();

myShadingFunction = myGetFunction (colorspace);

shading = CGShadingCreateRadial (colorspace,

startPoint, startRadius,

endPoint, endRadius,

myShadingFunction,

false,false);

myTransform = CGAffineTransformMakeScale (width, height);

CGContextConcatCTM (myContext, myTransform);

CGContextSaveGState (myContext);

CGContextClipToRect (myContext, CGRectMake(0,0,1,1));

CGContextSetRGBFillColor (myContext,1,1,1,1);

CGContextFillRect (myContext, CGRectMake(0,0,1,1));

CGContextDrawShading (myContext, shading);

CGColorSpaceRelease (colorspace);

CGShadingRelease (shading);

CGFunctionRelease (myShadingFunction);

CGContextRestoreGState (myContext);

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Quartz為創(chuàng)建漸變提供了CGShadingRef和CGGradientRef兩種不透明的數(shù)據(jù)類型。您可以使用其...
    權(quán)宜平和閱讀 854評(píng)論 0 0
  • Quartz 為顏色漸變提供兩種不透明的數(shù)據(jù)類型--------CGShadingRef 和 CGGradient...
    雪_晟閱讀 378評(píng)論 0 0
  • Quartz2D 編程指南(一)概覽、圖形上下文、路徑、顏色與顏色空間 Quartz2D 編程指南(二)變換、圖案...
    xuyafei86閱讀 1,988評(píng)論 0 21
  • 親愛的姑娘,從今天起,你就真正26歲了,已經(jīng)開始吃27歲的飯了,話說奔三也就是兩三年的事了。 畢業(yè)四年的年的你雖本...
    蘇穆涼閱讀 439評(píng)論 4 0
  • 對(duì)自己 對(duì)世界 對(duì)存在 依然困惑 依然不知所措 依然在不停的尋找生命中那失落的一角 尋尋覓覓,兜兜轉(zhuǎn)轉(zhuǎn) 對(duì)于生命 ...
    小飛俠303閱讀 308評(píng)論 0 2