iOS開發CoreGraphics核心圖形框架之六——梯度漸變

iOS開發CoreGraphics核心圖形框架之六——梯度漸變

1、引言

   關於顏色梯度漸變視圖的建立,CoreGraphics框架中提供了兩個類型CGShadingRef與CGGradientRef。CoreGraphics框架在繪製梯度漸變時,有兩種繪製方式,分別爲軸向繪製與徑向繪製。軸向繪製是指肯定兩個點,起點與終點鏈接的直線做爲梯度漸變的軸,垂直於此軸的線共享相同的顏色,由起點向終點進行顏色漸變。徑向漸變是指由兩個圓鏈接成圓臺,在同一圓周上的全部點共享相同的顏色,由起始圓向終點圓進行顏色漸變。數組

軸向漸變:框架

徑向漸變:函數

    前面說到,CGShadingRef與CGGradientRef均可以用於建立梯度漸變視圖,這兩個類型在使用使又有一些不一樣,CGShadingRef在使用使須要開發者爲其提供一個顏色計算方法,CGGradientRef則不須要,相比之下,CGGradientRef更像是爲了方便開發者使用而從CGShadingRef中擴展出的一個類型。測試

2、使用CGGradientRef建立梯度漸變視圖    

    建立一個UIView子類,在其drawRect:方法中編寫以下測試代碼:ui

-(void)drawRect:(CGRect)rect{
    CGGradientRef gradientRef;
    CGColorSpaceRef colorSpaceRef;
    CGFloat locs[2] = {0,1};
    CGFloat colors[8] = { 1.0, 0, 0, 1.0,  // 前4個爲起始顏色的rgba
        0, 1, 0, 1.0 }; // 後4個爲結束顏色的rgba
    colorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    gradientRef = CGGradientCreateWithColorComponents (colorSpaceRef, colors,
                                                       locs, 2);
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //這個方法用於建立軸向漸變
//    CGContextDrawLinearGradient(contextRef, gradientRef, rect.origin, CGPointMake(rect.origin.x+rect.size.width, rect.origin.y+rect.size.height), 0);
    //這個方法用於建立徑向漸變
    CGContextDrawRadialGradient(contextRef, gradientRef, CGPointMake(rect.origin.x+rect.size.width/2, rect.origin.y+rect.size.height/2), rect.size.width/2, CGPointMake(rect.origin.x+rect.size.width/2, rect.origin.y+rect.size.height/2), rect.size.width/4, 0);
}

CGContextDrawRadiaGradient()方法中的參數解析以下:spa

/*
c:繪圖上下文
gradieent:漸變對象
startCenter:漸變起始圓心
startRadius:漸變起始圓半徑
endCenter:漸變終止圓心
endRadius:漸變終止圓半徑
options:漸變的填充風格 設置爲0則不進行填充
typedef CF_OPTIONS (uint32_t, CGGradientDrawingOptions) {
  kCGGradientDrawsBeforeStartLocation = (1 << 0), //起點之前也進行填充
  kCGGradientDrawsAfterEndLocation = (1 << 1)    //終點以後也進行填充
};
*/    
CG_EXTERN void CGContextDrawRadialGradient(CGContextRef cg_nullable c,
    CGGradientRef cg_nullable gradient, CGPoint startCenter, CGFloat startRadius,
    CGPoint endCenter, CGFloat endRadius, CGGradientDrawingOptions options)
    CG_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);

CGGradient中定義的方法解析以下:指針

//獲取CGGradient類在CoreGraphics框架中的id
CFTypeID CGGradientGetTypeID(void);
//建立CGGradientRef
/*
space:色彩空間
components:色值數組
locations:漸變臨界點
count:locations數組中元素個數
*/
CGGradientRef __nullable CGGradientCreateWithColorComponents(
    CGColorSpaceRef cg_nullable space, const CGFloat * cg_nullable components,
    const CGFloat * __nullable locations, size_t count);
//建立CGGradientRef 這個方法locations中的元素個數須要與colors中的對應
/*
space:色彩空間
colors:顏色數組
locations:漸變臨界點
*/
CGGradientRef __nullable CGGradientCreateWithColors(
    CGColorSpaceRef __nullable space, CFArrayRef cg_nullable colors,
    const CGFloat * __nullable locations);
//進行引用計數+1
CGGradientRef cg_nullable CGGradientRetain(
    CGGradientRef cg_nullable gradient);
//進行引用計數-1
void CGGradientRelease(CGGradientRef cg_nullable gradient);

3、CGShadingRef的應用

       CGShadingRef的使用就不像CGGradientRef那麼方便,其中方法解析以下:code

//獲取CGShadingRef在CoreGraphics框架中的id
CFTypeID CGShadingGetTypeID(void);
//建立軸向漸變的CGShadingRef對象
/*
space:色彩空間
start:起始點
end:結束點
function:顏色計算函數
extendStart:是否填充起始點之前
extendEnd:是否填充結束點以後
*/
CGShadingRef __nullable CGShadingCreateAxial(
    CGColorSpaceRef cg_nullable space, CGPoint start, CGPoint end,
    CGFunctionRef cg_nullable function, bool extendStart, bool extendEnd);
//建立徑向漸變的CGShadingRef對象 參數同上
CGShadingRef __nullable CGShadingCreateRadial(
    CGColorSpaceRef cg_nullable space,
    CGPoint start, CGFloat startRadius, CGPoint end, CGFloat endRadius,
    CGFunctionRef cg_nullable function, bool extendStart, bool extendEnd);
//引用計數+1
CGShadingRef cg_nullable CGShadingRetain(CGShadingRef cg_nullable shading);
//引用計數-1
void CGShadingRelease(CGShadingRef cg_nullable shading);

示例代碼以下:component

//顏色計算函數
/*
info 是開發者後面將傳入的色彩空間的參數個數
in 爲輸入參數 對應0-1之間
out 爲輸出參數 爲所對應顏色空間的每一個色值
*/
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++ 的做用是指針右移 out指針能夠理解爲數組 右移做用和數組賦值一致
        *out++ = (1 + sin(*in * frequency[k]))/2;
   //最後追加上透明度值
    *out++ = 1; // alpha
}

-(void)drawRect:(CGRect)rect{
    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,
        &myCalculateShadingValues,
        NULL };
    //獲取色彩空間的色值數
    numComponents = 1 + CGColorSpaceGetNumberOfComponents (CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB));
    //建立CGFunctionRef
    CGFunctionRef func =  CGFunctionCreate ((void *) numComponents,
                             1,
                             input_value_range,
                             numComponents,
                             output_value_ranges,
                             &callbacks);
   
     
    CGPoint startPoint, endPoint;
    CGFloat startRadius, endRadius;
    CGAffineTransform myTransform;
    //起始圓位置
    startPoint = CGPointMake(0.25,0.3);
    //半徑
    startRadius = .1;
    //終止圓位置
    endPoint = CGPointMake(.7,0.7);
    //半徑
    endRadius = .25;
    //建立CGShadingRef
    CGShadingRef myShading =  CGShadingCreateRadial (CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB),
                           startPoint,
                           startRadius,
                           endPoint,
                           endRadius,
                           func,
                           false,
                           false);
    CGContextRef context = UIGraphicsGetCurrentContext();
    //進行transform的映射
    myTransform = CGAffineTransformMakeScale(320, 568);
    CGContextConcatCTM(context, myTransform);
    CGContextSaveGState(context);
    //進行繪製
    CGContextDrawShading(context, myShading);

    
}

上面的示例代碼效果以下圖:orm

4、一些小技巧

    靈活的應用CGContextDrawRadialGradient()方法能夠建立出僞立體效果的圖形,例如以下代碼:

-(void)drawRect:(CGRect)rect{
    CGGradientRef gradientRef;
    CGColorSpaceRef colorSpaceRef;
    CGFloat locs[2] = {0,1};
    CGFloat colors[8] = { 1.0, 0, 0, 1.0,  // 前4個爲起始顏色的rgba
        1, 1, 1, 1.0 }; // 後4個爲結束顏色的rgba
    colorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    gradientRef = CGGradientCreateWithColorComponents (colorSpaceRef, colors,
                                                       locs, 2);
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    CGContextDrawRadialGradient(contextRef, gradientRef, CGPointMake(rect.origin.x+rect.size.width/2, rect.origin.y+rect.size.height/2), rect.size.width/2, CGPointMake(rect.origin.x+rect.size.width/2, rect.origin.y+rect.size.height/2-100), 0, 0);
}

經過調整內圓的位置和半徑,能夠作到光影的移動,效果以下:

           

//模擬金屬原子
-(void)drawRect:(CGRect)rect{
    CGGradientRef gradientRef;
    CGColorSpaceRef colorSpaceRef;
    CGFloat locs[8] = {0,0.2,0.4,0.5,0.6,0.8,0.9,1.0};
    CGFloat colors[64] = { 1.0, 0, 0, 1.0,  // 前4個爲起始顏色的rgba
        0.0, 1, 0, 1.0,
        0.0, 0, 1, 1.0,
        1.0, 0, 0, 1.0,
        0.0, 1, 0, 1.0,
        1.0, 0, 0, 1.0,
        1.0, 1, 0, 1.0,
        1, 1, 1, 1.0 }; // 後4個爲結束顏色的rgba
    colorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    gradientRef = CGGradientCreateWithColorComponents (colorSpaceRef, colors,
                                                       locs, 8);
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
//    CGContextDrawLinearGradient(contextRef, gradientRef, rect.origin, CGPointMake(rect.origin.x+rect.size.width, rect.origin.y+rect.size.height), 0);
    CGContextDrawRadialGradient(contextRef, gradientRef, CGPointMake(rect.origin.x+rect.size.width/2, rect.origin.y+rect.size.height/2), rect.size.width/2, CGPointMake(rect.origin.x+rect.size.width/2, rect.origin.y+rect.size.height/2-100), 0, 0);
}

專一技術,熱愛生活,交流技術,也作朋友。

——琿少 QQ羣:203317592

相關文章
相關標籤/搜索