原博地址:http://blog.csdn.net/hello_hwc/article/details/49507881
Shadow
Shadow(陰影) 的目的是為了使UI更有立體感,如圖
shadow 主要有三個影響因素
x off-set 決定陰影沿着X的偏移量 y off-set 決定陰影沿着y的偏移量 blur value 決定了陰影的邊緣區域是不是模糊的
其中不同的blur效果的圖
注意:
shadow也是和繪制狀態相關的,意味着如果僅僅繪制一個subPath的shadow,注意save和restore
相關函數
CGContextSetShadow CGContextSetShadowWithColor//唯一區別是設置了陰影顏色
參數
context 繪制畫板
offset陰影偏移量,參考context的坐標系
blur 非負數,決定陰影的模糊程度
示例代碼
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); //填充邊框 當然你可以用layer設置 CGContextSetStrokeColorWithColor(context, [UIColor darkGrayColor].CGColor); CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); CGContextFillRect(context, rect); CGContextStrokeRect(context, rect); CGContextAddArc(context, 100, 100, 50, 0, M_2_PI, 0); CGContextSetLineCap(context, kCGLineCapRound); CGContextSetLineWidth(context, 3.0); CGContextSetShadow(context, CGSizeMake(4.0, 4.0), 1.0); //CGContextSetShadowWithColor(context, CGSizeMake(4.0, 4.0), 1.0, [UIColor blueColor].CGColor); CGContextStrokePath(context); }
效果
Gradient 漸變色
漸變無非就是從一種顏色逐漸變換到另一種顏色,Quartz 2D提供了兩種漸變的模型。
Quartz提供了兩個不透明數據odgago創建漸變:CGShadingRef 和 CGGradientRef.我們可以使用任何一個來創建軸向(axial)或徑向(radial)漸變。一個 漸變是從一個顏色到另外一個顏色的填充。
一個軸向漸變(也稱為線性漸變)沿着兩個端點連接的軸線漸變。所有位於垂直於軸線的的某條線上的點都具有相同的顏色值。
一個徑向漸變也是沿着兩個端點連接的軸線漸變,不過路徑通常由兩個圓來定義。
1> axial gradient 線性漸變(軸向漸變),使用的時候設置好兩個頂點的顏色 (也可以設置中間過渡色)
例如:
軸向漸變由橙色向黃色漸變 在這個例子中漸變軸相對於遠點傾斜了四十五度角。
Quartz 也允許我們設置一系列的顏色值和位置值,以沿着軸來創建更復雜的軸向漸變。如下圖所示,起始點的顏色設置為紅色(可以看一下Quartz 的坐標系 零點默認就是左下角),結束點的顏色是紫羅蘭色。同時,在軸上有5個位置,它們的顏色分別設置為橙 黃 綠 藍 和 靛藍。我們可以把它看成沿着同一軸線的六段連續的線性漸變。另外軸線的角度 有我們設置的兩個端點來定義。
2> radial gradient(徑向漸變)
這種模式的漸變允許 一個圓到另一個圓的漸變
如下圖所示,他從一個小的明亮的紅色圓漸變到一個大小黑色的圓,
我們可以把一個圓放置到一個徑向漸變中來創建各種形狀。如果一個圓是另一個的一部分或者完全在另一個的外面,則Quartz創建了圓錐和一個圓柱。徑向漸變的一個通常用法就是創建一個球體陰影
一個單一的點(半徑為0的圓)位於一個大圓以內。
CGShading 和 CGGradient對象的對比
我們有兩個對象類型用於創建漸變,你可能想知道哪一個更好用,看了下面你就會知道了。
CGshadingRef這個不透明的數據類型給我們更多的控制權,以確定如何計算每個端點的顏色,在我們創建CGShading對象之前,我們必須創建一個CGFunction對象(CGFunctionRef),這個對象定義了一個用於計算漸變色的函數。寫一個自定義的函數讓我們創建平滑的漸變。
當我們創建一個CGShading對象時,我們指定其是軸向還是徑向,除了計算函數以外,我們還需要提供一個顏色空間。起始點 結束點 或者是半徑,這取決於繪制軸向還是徑向漸變。在繪制時,我們只是簡單的傳遞CGShading對象以及繪制上下文給CGContextDrawShading函數,Quartz為漸變上的每個點調用漸變計算函數。
一個CGGRadient對象是CGShading對象的子集,其更容易使用,CGGradientRef不透明類型抑郁作用,因為Quartz在漸變的每一點上計算顏色值。我們不需要提供一個漸變計算函數。當創建好一個漸變對象的時候,我們提供一個位置和顏色的數組。quartz使用對應的顏色值來計算每個梯度的漸變。我們可以使用單一的氣勢與結束點來設置一個漸變對象。或者提供一組斷電來創建一個多顏色漸變的效果。使用CGShading對象可以提供多於兩個位置的能力。
當我們創建一個CGGradient對象時,我們需要設置一個顏色空間、位置、和每個位置對應的顏色值。當使用一個漸變對象繪制上下文時,我們指定Quartz是繪制一個軸向還是徑向漸變。在繪制時,我們指定開始結束點或半徑,這取決於我們是繪制軸向還是徑向漸變。而CGShading的幾何形狀是在創建時定義的,而不是繪制時。
擴展漸變端點外部的顏色
當我們創建一個漸變時,我們可以選擇使用純色來填充漸變端點外部的空間。Quartz使用使用漸變邊界上的顏色作為填充顏色。我們可以擴展漸變起點、終點或兩端的顏色。我們可以擴展使用CGShading對象或CGGradient對象創建的軸向或徑向漸變。
圖演示了一個軸向漸變,它擴展了起點和終點兩側的區域。圖片中的線段顯示了漸變的軸線。我們可以看到,填充顏色與起點和終點的顏色是對應的。
通過 這兩種漸變的嵌套使用 Quartz 2D能繪制出非常漂亮的圖形
漸變的兩種繪制模型
CGShading -使用這種數據類型需要自己定義CFFunction來計算每一個點的漸變色,較為復雜,但是能夠靈活的繪制。
CGGradient-使用這種數據類型只需要制定兩個頂點的顏色,以及繪制模式,其余的Quartz會給繪制,但是漸變的數學模型不靈活。
使用CGGradient對象:
一個CGGradient 對象是一個漸變的抽象定義 他簡單的質地昂了顏色值和位置,但沒有指定任何幾何形狀,我們可以在軸向和徑向幾何形狀中使用這個對象,作為一個軸向定義,CGGradient對象可能比CGShading對象更容易重用。沒有講任何幾何形狀存儲在CGGradient對象中。這樣允許我們使用相同的顏色方案來繪制不同的幾何圖形,而不需要為多個圖形創建多個CGGadient對象。
因為Quartz為我們計算漸變,使用一個CGGradient對象來創建和繪制一個漸變則更直接,只需要以下幾步:
1>創建一個CGGradient對象,提供一個顏色空間,一個飽含兩個或更多顏色組件的數組,一個包含兩個或多個位置的數組,和兩個數組中元素的個數。
2>使用CGContextDrawLinearGradient或者CGContentDrawRadialGradient繪制。
3>釋放CGGradient對象
一個位置是一個值區間在0.0到1.0之間的CGFloat值,他指定了沿着漸變的軸線的標准化距離值0.0的值指定軸線的起點,1.0的值指定了軸線的重點。其他值指定了一個距離的比例。最低限度情況下,Quartz使用兩個位置值。如果我們傳遞NULL值作為位置數組參數,則Quartz使用0作為第一個位置,1作為第二個位置。
每個顏色的顏色組件的數目取決於顏色空間。對於離屏繪制,我們使用一個RGB顏色空間。因為Quartz使用alpha來繪制,每個離屏顏色都有四個組件—紅、綠、藍和alpha。所以,對於離屏繪制,我們提供的顏色組件數組的元素的數目必須是位置數目的4倍。Quartz的RGBA顏色組件可以在0.0到1.0之間改變。
代碼
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); //使用CGGradient繪制 CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB(); size_t num_of_locations = 2;
//注意每個位置對應一個顏色 CGFloat locations[2] = {0.0,1.0}; CGFloat components[8] = {1.0,0.0,0.0,1.0,//紅色 0.0,1.0,0.0,1.0};//綠色 CGGradientRef gradient = CGGradientCreateWithColorComponents(deviceRGB, components, locations, num_of_locations); CGPoint startPoint = CGPointMake(0, 0); CGPoint endPoint = CGPointMake(rect.size.width, rect.size.height); CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); CGColorSpaceRelease(deviceRGB); CGGradientRelease(gradient); }
效果
徑向漸變
CGContextRef context = UIGraphicsGetCurrentContext(); //顏色空間 CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB(); //位置數組和顏色數組包含元素的個數 size_t num_of_locations = 2; CGFloat locations[2] = {0.0,1.0}; CGFloat components[8] = {0.0,0.0,1.0,1.0,//白色 0.0,1.0,0.0,1.0};//黑色 CGGradientRef gradient = CGGradientCreateWithColorComponents(deviceRGB, components, locations, num_of_locations); CGPoint startCenter = CGPointMake(100, 100); CGPoint endCenter = CGPointMake(125, 125); CGFloat startRadius = 0.0; CGFloat endRadius = 50.0; CGContextDrawRadialGradient(context, gradient, startCenter, startRadius, endCenter, endRadius, 0); CGColorSpaceRelease(deviceRGB); CGGradientRelease(gradient);
使用CGShading對象
我們通過調用函數CGShadingCreateAxial或者CGShadingCreateRadial創建一個CGShading對象來設置一個漸變,調用這些函數需要提供以下參數。
1.CGColorSpace 對象:顏色空間
2.起始點和終點。對於軸向漸變,有軸向的起始點和和終點的坐標,對於徑向漸變,有起始圓和終點圓的中心坐標
3.用於定義漸變區域的圓的啟示半徑和終止半徑
4.一個CGFunction對象,可以通過CGFunctionCreate函數來獲取。這個回調例程必須返回繪制到特定點的顏色值。
5.一個布爾值用於指定是否適用純色來繪制起始點和終點的擴展區域
我們提供給CGShading創建函數的CGFunction對象包含一個回調結構體,及Quartz需要實現這個回調的所有信息。也許設置CGShasing對象的最棘手的部分是創建CGFunction對象。當我們調用CGFunctionCreate函數時,我們提供以下參數:
CGFunctionRef _Nullable CGFunctionCreate ( void * _Nullable info, size_t domainDimension, const CGFloat * _Nullable domain, size_t rangeDimension, const CGFloat * _Nullable range, const CGFunctionCallbacks * _Nullable callbacks );
看到這就很頭疼啊?當然,CGGradient對象足矣滿足大部分時候的需求,不過有空的話還是耐心下來看看吧。我們先看看參數
info 用來傳遞到callback的數據(就是指向回調所需要的數據的指針),注意他的生命周期可能不只是方法的生命周期
domainDimesion 輸入的數量,quart中,就是1。(回調輸入值的個數,Quartz要求回調攜帶一個輸入值)
domain 一組數據 確定輸入的有效間隔,在Quartz中是0到1,0表示開始,1表示結束 (一個浮點數的數組。Quartz只會提供數組中的一個元素給回調函數。一個轉入值的范圍是0(漸變的開始點的顏色)到1(漸變的結束點的顏色)。)
rangDimension 輸出的數量:(回調提供的輸出值的數目,對於每一個輸入值,我們的回調必須為每個顏色組件提供一個值,以及一個alpha值來指定透明度,顏色組件值由Quartz提供的顏色空間來解釋,並提供給CGShading創建函數。例如如果我們使用RGB顏色空間,則我們提供4作為輸出值(R,G,B,A)的數目)
rang 輸出的有效間隔 (一個浮點數的數組,用於指定每個顏色組件的值及alpha值)
callbacks 用來計算的實際方法 (一個回調數據結構,包含結構體的版本(設置為0)、生成顏色組件值的回調、一個可選的用於釋放回調中info參數表示的數據。)格式如下 格式如下void myCalculateShadingValues (void *info, const CGFloat *in, CGFloat *out)
在創建CGShading對象后,如果需要我們可以設置額外的裁減操作。然后調用CGContextDrawShading函數來使用漸變來繪制上下文的裁減區域。當調用這個函數時,Quartz調用回調函數來獲取從起點到終點這個范圍內的顏色值。
當不再需要CGShading對象時,我們調用CGShadingRelease來釋放它。
首先設置CGFunction對象來計算顏色值
我們可以以我們想要的方式來計算顏色值,我們的顏色計算函數包含以下三個參數:
1.void *info 這個值可以為NULL 或者是一個指向傳遞給CGShading創建函數的數據
2.const CGFloat *in Quartz傳遞in數組給回調。數組中的值必須在為CGFunction對象定義的輸入值范圍內
3.我們的回調函數傳遞out數組給Quartz。它包含用於顏色空間中每個顏色組件的元素及一個alpha值。輸出值應該在CGFunction對象中定義的輸出值的范圍內
static void myCalculateShadingValues (void *info, const CGFloat *in, CGFloat *out) { CGFloat v; size_t k, components; static const CGFloat c[] = {1, 0, 0.5, 0 }; components = (size_t)info; v = *in; for (k = 0; k < components -1; k++) *out++ = c[k] * v; *out++ = 1; }
這里的三個參數,函數很簡單out的值(r,g,b,a)分別為(in*1,in*0.in*0.5,1)
創建一個CGFuction
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, 1, input_value_range, numComponents, output_value_ranges, &callbacks); }
其中,每一行分別為
以colorspace作為參數
定義callback函數
計算顏色域中的顏色組建的個數,例如RGB就是三個,然后加一,表示alpha通道
用CGShading繪制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) CGContextDrawShading (myContext, myShading); CGShadingRelease (myShading); CGColorSpaceRelease (colorspace); CGFunctionRelease (myFunctionObject);
用CGShading繪制Radial Gradient
callback
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 }
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) CGContextDrawShading (myContext, shading); CGShadingRelease (myShading); CGColorSpaceRelease (colorspace); CGFunctionRelease (myFunctionObject);
具體效果請看 這里 http://www.tuicool.com/articles/biieum
我的水平還是有點看不懂啊