三、CGShadingRef的应用
CGShadingRef的使用就不像CGGradientRef那么方便,其中方法解析如下:
//获取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);
示例代码如下:
//颜色计算函数
/*
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);
}
上面的示例代码效果如下图:
四、一些小技巧
灵活的应用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);
}
