iPhone之Quartz 2D系列--陰影和透明層(5)Shadows&Transparency Layers

以下幾遍關於Quartz 2D博文都是轉載自:http://www.cocoachina.com/bbs/u.php?action=topic&uid=38018

iPhone之Quartz 2D系列--陰影和透明度(5)Shadows&物Transparency Layers

陰影是繪製在一個圖形對象下的且有一定偏移的圖片,它用於模擬光源照射到圖形對象上所形成的陰影效果,如果7-1所示。文本也可以有陰影。陰影可以讓一幅圖像看上去是立體的或者是浮動的。

 

陰影有三個屬性:
  • x偏移值,用於指定陰影相對於圖片在水平方向上的偏移值。
  • y偏移值,用於指定陰影相對於圖片在豎直方向上的偏移值。
  • 模糊(blur)值,用於指定圖像是有一個硬邊(hard edge,如圖7-2左邊圖片所示),還是一個漫射邊(diffuse edge,如圖7-1右邊圖片所示)


 

本章將描述陰影是如何工作的及如何用Quartz 2D API來創建陰影。


陰影是如何工作的
Quartz中的陰影是圖形狀態的一部分。我們可以調用函數CGContextSetShadow來創建,並傳入一個圖形上下文、偏移值及模糊值。陰影被設置後,任何繪製的對象都有一個陰影,且該陰影在設備RGB顏色空間中呈現出黑色的且alpha值爲1/3。換句話說,陰影是用RGBA值{0, 0, 0, 1.0/3.0}設置的。
我們可以調用函數CGContextSetShadowWithColor來設置彩色陰影,並傳遞一個圖形上下文、 偏移值、模糊值有CGColor顏色對象。顏色值依賴於顏色空間。
如何在調用CGContextSetShadow或CGContextSetShadowWithColor之前保存了圖形狀態,我們可以通過恢復圖形狀態來關閉陰影。我們也可以通過設置陰影顏色爲NULL來關閉陰影。

基於圖形上下文的陰影繪製慣例
偏移值指定了陰影相對於相關圖像的位置。這些偏移值由圖形上下文來描述,並用於計算陰影的位置:
  • 一個正值的x偏移量指定陰影位於圖形對象的右側。
  • 在Mac OS X中,正值的y指定陰影位於圖形對象的上邊,這與Quartz 2D默認的座標值匹配。
  • 在iOS中,如果我們用Quartz 2D API來創建PDF或者位圖圖形上下文,則正值的y指定陰影位於圖形對象的上邊。
  • 在iOS中,如果圖形上下文是由UIKit創建的,則正值的y指定陰影位於圖形對象的下邊。這與UIKit座標系統相匹配。陰影繪製慣例不受CTM影響
繪製陰影
按照如下步驟來繪製陰影
  1. 保存圖形狀態
  2. 調用函數CGContextSetShadow,傳遞相應的值
  3. 使用陰影繪製所有的對象
  4. 恢復圖形狀態
按照如下步驟來繪製彩色陰影
  1. 保存圖形狀態
  2. 創建一個CGColorSpace對象,確保Quartz能正確地解析陰影顏色
  3. 創建一個CGColor對象來指定陰影的顏色
  4. 調用CGContextSetShadowWithColor,並傳遞相應的值
  5. 使用陰影繪製所有的對象
  6. 恢復圖形狀態
圖7-3顯示了兩個帶有陰影的矩形,其中一個是彩色陰影。

 

列表清單顯示瞭如何創建圖7-3中的圖像。
複製代碼
  1. Listing 7-1  A function that sets up shadows
  2. void MyDrawWithShadows (CGContextRef myContext, float wd, float ht);
  3. {
  4.     CGSize          myShadowOffset = CGSizeMake (-15,  20);
  5.     float           myColorValues[] = {1, 0, 0, .6};
  6.     CGColorRef      myColor;
  7.     CGColorSpaceRef myColorSpace;
  8.     CGContextSaveGState(myContext);
  9.     CGContextSetShadow (myContext, myShadowOffset, 5); 
  10.     // Your drawing code here
  11.     CGContextSetRGBFillColor (myContext, 0, 1, 0, 1);
  12.     CGContextFillRect (myContext, CGRectMake (wd/3 + 75, ht/2 , wd/4, ht/4));
  13.     myColorSpace = CGColorSpaceCreateDeviceRGB ();
  14.     myColor = CGColorCreate (myColorSpace, myColorValues);
  15.     CGContextSetShadowWithColor (myContext, myShadowOffset, 5, myColor);
  16.     // Your drawing code here
  17.     CGContextSetRGBFillColor (myContext, 0, 0, 1, 1);
  18.     CGContextFillRect (myContext, CGRectMake (wd/3-75,ht/2-100,wd/4,ht/4));
  19.     CGColorRelease (myColor);
  20.     CGColorSpaceRelease (myColorSpace); 
  21.     CGContextRestoreGState(myContext);
  22. }

透明層

透明層(TransparencyLayers)通過組合兩個或多個對象來生成一個組合圖形。組合圖形被看成是單一對象。當需要在一組對象上使用特效時,透明層非常有用,如圖9-1所示的給三個圓使用陰影的效果。

 

如果沒有使用透明層來渲染圖9-1中的三個圓,對它們使用陰影的效果將是如圖9-2所示:

 

透明層的工作方式
Quartz的透明層類似於許多流行的圖形應用中的層。層是獨立的實體。Quartz維護爲每個上下文維護一個透明層棧,並且透明層是可以嵌套的。但由於層通常是棧的一部分,所以我們不能單獨操作它們。

我們通過調用函數CGContextBeginTransparencyLayer來開始一個透明層,該函數需要兩個參數:圖形上下文與CFDictionary對象。字典中包含我們所提供的指定層額外信息的選項,但由於Quartz 2D API中沒有使用字典,所以我們傳遞一個NULL。在調用這個函數後,圖形狀態參數保持不變,除了alpha[默認設置爲1]、陰影[默認關閉]、混合模式[默認設置爲normal]、及其它影響最終組合的參數。

在開始透明層操作後,我們可以繪製任何想顯示在層上的對象。指定上下文中的繪製操作將被當成一個組合對象繪製到一個透明背景上。這個背景被當作一個獨立於圖形上下文的目標緩存。

當繪製完成後,我們調用函數CGContextEndTransparencyLayerQuartz將結合對象放入上下文,並使用上下文的全局alpha值、陰影狀態及裁減區域作用於組合對象。

在透明層中進行繪製


在透明層中繪製需要三步:
1. 調用函數CGContextBeginTransparencyLayer
2. 在透明層中繪製需要組合的對象
3. 調用函數CGContextEndTransparencyLayer

9-3顯示了在透明層中繪製三個矩形,其中將這三個矩形當成一個整體來渲染陰影。

 

代碼清單9-1顯示瞭如何利用透明層生成圖9-3所示的矩形。

複製代碼
  1. void MyDrawTransparencyLayer (CGContext myContext, float wd,float ht)
  2. {
  3.     CGSize          myShadowOffset = CGSizeMake (10, -20);
  4.     CGContextSetShadow (myContext, myShadowOffset, 10);   
  5.     CGContextBeginTransparencyLayer (myContext, NULL);
  6.     // Your drawing code here
  7.     CGContextSetRGBFillColor (myContext, 0, 1, 0, 1);
  8.     CGContextFillRect (myContext, CGRectMake (wd/3+ 50,ht/2 ,wd/4,ht/4));
  9.     CGContextSetRGBFillColor (myContext, 0, 0, 1, 1);
  10.     CGContextFillRect (myContext, CGRectMake (wd/3-50,ht/2-100,wd/4,ht/4));
  11.     CGContextSetRGBFillColor (myContext, 1, 0, 0, 1);
  12.     CGContextFillRect (myContext, CGRectMake (wd/3,ht/2-50,wd/4,ht/4));
  13.     CGContextEndTransparencyLayer (myContext);
  14. }




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章