Quartz 2D編程指南 (十) —— 漸變(一)

版本記錄

版本號(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)建漸變 - CGShadingRefCGGradientRef蝌麸。您可以使用其中任何一個(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度角。

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

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)定義。

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周偎,您不僅可以根據(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。

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

您可以將圓放置在徑向漸變中以創(chuàng)建各種形狀面氓。 如果一個(gè)圓部分或完全位于另一個(gè)圓之外兵钮,則Quartz為具有不等圓周的圓形創(chuàng)建圓錐曲面,為圓周具有相等圓周的圓柱曲面創(chuàng)建圓錐曲面舌界。 徑向漸變的常見用法是創(chuàng)建陰影球體掘譬,如圖8-5所示。 在這種情況下呻拌,單個(gè)點(diǎn)(半徑為0的圓)位于較大的圓內(nèi)葱轩。

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

您可以通過嵌套幾個(gè)類似于圖8-6中所示形狀的徑向漸變來創(chuàng)建更復(fù)雜的效果。 形狀的環(huán)形部分使用同心圓形成柏锄。

Figure 8-6 Nested radial gradients

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 ObjectUsing a CGShading Object中所示格粪。

圖8-7顯示了在起始位置和結(jié)束位置都延伸的軸向梯度躏吊。 圖中的線顯示了漸變的軸肺孵。 如您所見,填充顏色對(duì)應(yīng)于起點(diǎn)和終點(diǎn)的顏色颜阐。

Figure 8-7 Extending an axial gradient

圖8-8將不使用擴(kuò)展選項(xiàng)的徑向漸變與使用擴(kuò)展選項(xiàng)的徑向漸變比較起始位置和結(jié)束位置平窘。 Quartz采用起始和結(jié)束顏色值,并使用這些純色來擴(kuò)展表面凳怨,如圖所示瑰艘。 該圖顯示了起始圓和結(jié)束圓,以及漸變的軸肤舞。

Figure 8-8 Extending a radial gradient

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)用CGContextDrawLinearGradientCGContextDrawRadialGradient并提供上下文琴儿,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);
Figure 8-9 A radial gradient painted using a CGGradient object

圖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 };
Figure 8-10 An axial gradient with three locations

Using a CGShading Object - 使用CGShading對(duì)象

您可以通過創(chuàng)建調(diào)用函數(shù)CGShadingCreateAxialCGShadingCreateRadialCGShading對(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 ObjectPainting 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中所示的輸出。

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

要繪制圖中所示的軸向漸變颂郎,請(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所示的輸出硼婿。

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

要繪制徑向漸變,請(qǐng)按照以下各節(jié)中說明的步驟操作:

(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描述了使用CGGradientCGShading對(duì)象繪制到上下文的函數(shù)。

后記

本篇主要講述了漸變缝彬,感興趣的給個(gè)贊或者關(guān)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末萌焰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子谷浅,更是在濱河造成了極大的恐慌扒俯,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件一疯,死亡現(xiàn)場(chǎng)離奇詭異撼玄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)墩邀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門掌猛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人眉睹,你說我怎么就攤上這事荔茬。” “怎么了辣往?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵兔院,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我站削,道長(zhǎng)坊萝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任许起,我火速辦了婚禮十偶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘园细。我一直安慰自己惦积,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布猛频。 她就那樣靜靜地躺著狮崩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鹿寻。 梳的紋絲不亂的頭發(fā)上睦柴,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音毡熏,去河邊找鬼坦敌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的狱窘。 我是一名探鬼主播杜顺,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蘸炸!你這毒婦竟也來了躬络?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤搭儒,失蹤者是張志新(化名)和其女友劉穎洗鸵,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仗嗦,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年甘凭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了稀拐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡丹弱,死狀恐怖德撬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情躲胳,我是刑警寧澤蜓洪,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站坯苹,受9級(jí)特大地震影響隆檀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜粹湃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一恐仑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧为鳄,春花似錦裳仆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至偏形,卻和暖如春静袖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背壳猜。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工勾徽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓喘帚,卻偏偏與公主長(zhǎng)得像畅姊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子吹由,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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