最近在学习iOS Quartz2D二维图形绘制--->渐变效果
Quartz2D 渐变
Quartz提供了两个不透明数据odgago创建渐变: CGShadingRef 和 CGGradientRef
可以使用任何一种来创建轴向(axial)或径向(radial)渐变.一个渐变是从一个颜色到另一个颜色的填充
一个轴向渐变(也成为线性渐变)
不说废话直接上干货, 代码和注释还算全,不懂的自行百度吧
<span style="font-size:18px;">// Quartz2DViewThree.m // Quartz2DDemoOne // // Created by 帝炎魔 on 16/5/22. // Copyright © 2016年 帝炎魔. All rights reserved. // #import "Quartz2DViewThree.h" @implementation Quartz2DViewThree // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code [super drawRect:rect]; CGContextRef context = UIGraphicsGetCurrentContext(); /** * Quartz2D 渐变 Quartz提供了两个不透明数据odgago创建渐变: CGShadingRef 和 CGGradientRef 可以使用任何一种来创建轴向(axial)或径向(radial)渐变.一个渐变是从一个颜色到另一个颜色的填充 一个轴向渐变(也成为线性渐变) */ // [self myGradientWithstartPoint:CGPointMake(self.bounds.size.width, 0) endPoint:CGPointMake(0, self.bounds.size.height)]; // gradientColor(context, self.bounds); myPaintRadialShading(context, self.bounds); } #pragma mark ----- CGGradientCreateWithColorComponents 创建渐变图层 - (void)myGradientWithstartPoint:(CGPoint )startPoint endPoint:(CGPoint )endPoint { CGContextRef context = UIGraphicsGetCurrentContext(); CGPoint myStartPoint, myEndPoint; myStartPoint.x = startPoint.x; myStartPoint.y = startPoint.y; myEndPoint.x = endPoint.x; myEndPoint.y = endPoint.y; CGGradientRef myGradient; CGColorSpaceRef mycolorSpace; size_t num_locations = 4; CGFloat locations[4] = {0.0, 0.33, 0.66, 1.0}; // 设置4个点 CGFloat components[16] = {0.1, 1.0, 0.2, 1.0, // RGB alpha 1.0, 0.1, 0.1, 1.0, 0.1, 0.1, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; mycolorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); /** * CGGradient * * @param mycolorSpace 设置颜色空间 色调 * @param components 设置关键点颜色的数组 * @param locations 设置关键点的位置和个数 * @param num_locations 设置点的个数 * * @return CGGradient */ myGradient = CGGradientCreateWithColorComponents(mycolorSpace, components, locations, num_locations); // CGContextDrawRadialGradient(context, myGradient, myStartPoint, 300, myEndPoint, 300, kCGGradientDrawsBeforeStartLocation); CGContextDrawLinearGradient(context, myGradient, myStartPoint, myEndPoint, kCGGradientDrawsBeforeStartLocation); // 释放颜色空间对象 CGColorSpaceRelease(mycolorSpace); } /** * 使用CGShading对象绘制一个径向渐变 * * 使用CGShading对象来生成如下的图形 为了绘制一个径向渐变, 需要如下的步骤: 1. 设置CGFunction 对象来计算颜色值---->>> 要有一个方法去计算这个图形的颜色function 2. 创建径向渐变的CGShading对象 ----->>>> 创建CGShading对象来绘制渐变图形 3. 使用CGShading对象来绘制径向渐变 4, 释放对象 -----> 别忘了释放对象CGShading对象 */ #pragma mark ---- 渐变的圆的效果---> CGShading 绘制径向渐变的效果图案 void myPaintRadialShading(CGContextRef myContext, CGRect bounds) { CGPoint startPoint, // 渐变的起始点坐标 endPoint; // 渐变的终止的点坐标 CGFloat startRadius, endRadius; CGAffineTransform myTransform; CGFloat width = bounds.size.width; CGFloat height = bounds.size.height; /** * 初始点的坐标和终止点坐标 都是系统的坐标系标准 通过设置起始点和终止点的坐标和半径可以绘制各种图形 通过设置颜色function 可以得到五颜六色的图形 * * */ startPoint = CGPointMake(.4,.4); startRadius = 1.; endPoint = CGPointMake(.5,.5); endRadius = .01; // CMYK的模式的状态下 颜色会偏暗一点 CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); // 创建一个一个CGFunctionRef 的对象, 来计算颜色值 CGFunctionRef myShadingFunction = myGetFunction(colorspace); // 创建一个CGShadingRef来绘制径向渐变 /** * CGShadingRef * * @param colorspace CGColorSpace对象 颜色空间 * @param startPoint 起始点坐标 对于轴向的渐变, 有轴线的起始点和终止点, 对于径向渐变, 有起始圆和终止圆中心的坐标 * @param startRadius 起始点圆的半径--->用于定义渐变区域的圆的起始半径 * @param endPoint 终止点坐标 * @param endRadius 终止点圆的半径----> 用于定义渐变区域的圆的终止半径 * @param myShadingFunction CGFunction 用于计算颜色的函数 单独计算的函数 * @param extendStart false ----> 是否延伸到初始点 * @param extendEnd false ---> 是否延伸到终止点 * * @return 返回的是一个CGShadingRef的对象 配置好渐变的颜色空间, 起始点, 起始点圆的半径, 终止点, 终止点的圆半径, 颜色的返回函数, 得到这个对象之后, 开始绘制渐变图形 */ CGShadingRef shading = CGShadingCreateRadial(colorspace, startPoint, startRadius, endPoint, endRadius, myShadingFunction, false, false); // 取得图形的变换的CTM 矩阵 myTransform = CGAffineTransformMakeScale(width, height); CGContextConcatCTM(myContext, myTransform); // 保存图形的状态 context CGContextSaveGState(myContext); // 修剪Clip一个图形 CGContextClipToRect(myContext, CGRectMake(0, 0, 1, 1)); // 设置填充的RGB颜色 CGContextSetRGBFillColor(myContext, 1, 1, 1, 1); // 设置一个填充的图形的frame CGContextFillRect(myContext, CGRectMake(0, 0, 1, 1)); // 绘制Shading CGContextDrawShading(myContext, shading); // 注意 :别忘了 释放 颜色空间colorSpace , shading中间绘制对象, 计算颜色的方法CGFunction CGColorSpaceRelease(colorspace); // 释放 CGShading的对象 CGShadingRelease(shading); // 释放计算颜色值得函数对象 CGFunctionRelease(myShadingFunction); // 恢复状态 restore context CGContextRestoreGState(myContext); } /** * 设置CGFunction 对象来计算颜色值 * * 计算径向渐变和轴向渐变颜色值函数并没有什么区别, 我们可以按照上面的轴向的设置CGFunction对象来计算颜色值, 函数遵循相同的原型, 每个函数获取一个输入值并计算N个值, 即颜色空间的每个颜色组件加一个alpha值 写完颜色计算函数后调用它, 需要创建一个CGFunction对象, 如在轴向中设置CGFunction对象来计算颜色值 */ static void myCalculateShadingValues(void *info, const CGFloat *in, CGFloat *out) { size_t k, components; /** * double值数组 控制颜色 对组中对应的R,G,B,alpha等值 */ double frequency[4] = {220, 220, 220, 0}; components = (size_t)info; for(k = 0; k < components - 1; k++) // 通过一个sin函数给颜色空间一个RGB的值 *out++ = (1 + sin(*in * frequency[k])) / 2; *out = 1; } /** * myGetFunction 创建myFunction 给Shading一个颜色回调函数 * * */ static CGFunctionRef myGetFunction(CGColorSpaceRef colorspace) { // 创建一个CGFloat数组, value的值 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}; size_t numComponents = 1 + CGColorSpaceGetNumberOfComponents(colorspace); /** * CGFunctionCreate函数 * 1. 指向回调所需要的数据的指针, 2. 回调的输入值的个数, Quartz要求回调携带一个输入值 */ // 返回一个创建CGFunctionCreate CGFunction的方法 return CGFunctionCreate((void *)numComponents, 1, input_value_range, numComponents, output_value_ranges, &callbacks); } #pragma mark --- CGShading 轴向的渐变的效果 void gradientColor (CGContextRef myContext, CGRect bounds) { CGPoint startPoint, endPoint; CGAffineTransform myTransform; CGFloat width = bounds.size.width; CGFloat height = bounds.size.height; startPoint = CGPointMake(0,0.5); endPoint = CGPointMake(1,0.5); CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); CGFunctionRef myShadingFunction = myGetGradientFunction(colorspace); CGShadingRef shading = CGShadingCreateAxial(colorspace, startPoint, endPoint, myShadingFunction, false, false); myTransform = CGAffineTransformMakeScale(width, height); CGContextConcatCTM(myContext, myTransform); CGContextSaveGState(myContext); CGContextClipToRect(myContext, CGRectMake(0, 0, 1, 1)); CGContextSetRGBFillColor(myContext, 1, 1, 1, 1); CGContextFillRect(myContext, CGRectMake(0, 0, 1, 1)); CGContextBeginPath(myContext); CGContextAddArc(myContext, .5, .5, .3, 0, M_PI, 0); CGContextClosePath(myContext); CGContextClip(myContext); CGContextDrawShading(myContext, shading); CGColorSpaceRelease(colorspace); CGShadingRelease(shading); CGFunctionRelease(myShadingFunction); CGContextRestoreGState(myContext); } static CGFunctionRef myGetGradientFunction (CGColorSpaceRef colorspace) { 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, &myGradientCalculateShadingValues, NULL}; size_t numComponents = 1 + CGColorSpaceGetNumberOfComponents (colorspace); return CGFunctionCreate((void *)numComponents, 1, input_value_range, numComponents, output_value_ranges, &callbacks); } static void myGradientCalculateShadingValues(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; } @end</span>