这片文章说说iOS中关于gradient的处理。gradient这个词我还真不知道在中文里该怎么翻译,有没有专门的词来表达。在这里先不管他中文的名称,这里主要说说在直角坐标系中的使用。
gradient的具体操作就是将坐标系中一个点作为起点,另外选一个点作为终点,同时起点和终点都指定一种颜色,gradient来完成两个点间的颜色过渡。当然这些颜色不是只局限在一根直线上面,而是将颜色拓展到跟直线垂直的所有区域。可以这样理解,有了起点和终点,可以画一根线,在这根线上,随意画一根垂直的线,这根垂直线上的所有颜色都是相同的,等会可以通过例子来看到效果。
创建gradient可以用CGGradientCreateWithColorComponents,这个函数需要四个参数,第一个是colorSpace,这个可以通过简单调用CGColorSpaceCreateDeviceRGB来获得;第二个是color Components,我们拿RGBA颜色系来说,要表示一种颜色,需要4个值,这个等会在下面的例子可以看到;第三个是location of color,这个参数用来表明颜色过渡渐变的速度,这是一个数组,里面元素的个数必须要与第四个参数的值一致;第四个参数表明一共用了多少种颜色。
直接用代码来说明问题
- (void)drawGradient1 { /* 获得colorSpace */ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); /* 指定startColor,endColor并且拆分成元素数组 */ UIColor *startColor = [UIColor blueColor]; CGFloat *startColorComponents = (CGFloat *)CGColorGetComponents([startColor CGColor]); UIColor *endColor = [UIColor greenColor]; CGFloat *endColorComponents = (CGFloat *)CGColorGetComponents([endColor CGColor]); CGFloat colorComponents[8] = { /* Four components of the blue color (RGBA) */ startColorComponents[0], startColorComponents[1], startColorComponents[2], startColorComponents[3], /* Four components of the green color (RGBA) */ endColorComponents[0], endColorComponents[1], endColorComponents[2], endColorComponents[3] }; /* locations of color in color array */ CGFloat colorIndices[2] = { 0.0f, /* Color 0 in the colorComponents array */ 1.0f, /* Color 1 in the colorComponents array */ }; CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, (const CGFloat *)&colorComponents, (const CGFloat *)&colorIndices, 2); CGColorSpaceRelease(colorSpace); CGContextRef currentContext = UIGraphicsGetCurrentContext(); CGRect screenBounds = [[UIScreen mainScreen] bounds]; CGPoint startPoint, endPoint; startPoint = CGPointMake(0.0f, screenBounds.size.height / 2.0f); endPoint = CGPointMake(screenBounds.size.width, startPoint.y); CGContextDrawLinearGradient(currentContext, gradient, startPoint, endPoint, 0); CGGradientRelease(gradient); }
记得释放colorSpace和gradient的资源,最终效果如下
效果是这样的是因为我指定的start和end的点坐标分别为(0.0f, screenBounds.size.height / 2.0f)和(screenBounds.size.width, startPoint.y),他们连成的线位于屏幕的最中间,呈水平位置,如前面所说的,在这个直线上所有与他垂直的线都使用同一种颜色,水平线上每个点的颜色在blue和green之间渐变,所以就出现了上面的效果。
函数CGContextDrawLinearGradient的最后一个参数需要注意一下,它有几个可选值,kCGGradientDrawsBeforeStartLocation和kCGGradientDrawsAfterEndLocation,表明是否在startPoint之前填充颜色和是否在endPoint之后填充颜色,我们可以通过下面的例子来学习这个参数的意义
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); UIColor *startColor = [UIColor orangeColor]; CGFloat *startColorComponents = (CGFloat *)CGColorGetComponents([startColor CGColor]); UIColor *endColor = [UIColor blueColor]; CGFloat *endColorComponents = (CGFloat *)CGColorGetComponents([endColor CGColor]); CGFloat colorComponents[8] = { startColorComponents[0], startColorComponents[1], startColorComponents[2], startColorComponents[3], endColorComponents[0], endColorComponents[1], endColorComponents[2], endColorComponents[3] }; CGFloat colorIndices[2] = { 0.0f, 1.0f }; CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, (const CGFloat *)&colorComponents, (const CGFloat *)&colorIndices, 2); CGColorSpaceRelease(colorSpace); CGPoint startPoint, endPoint; startPoint = CGPointMake(120.0f, 260.0f); endPoint = CGPointMake(120.0f, 220.0f); CGContextRef currentContext = UIGraphicsGetCurrentContext(); CGContextSaveGState(currentContext); CGContextDrawLinearGradient(currentContext, gradient, startPoint, endPoint, CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); UIColor *startColor = [UIColor orangeColor]; CGFloat *startColorComponents = (CGFloat *)CGColorGetComponents([startColor CGColor]); UIColor *endColor = [UIColor blueColor]; CGFloat *endColorComponents = (CGFloat *)CGColorGetComponents([endColor CGColor]); CGFloat colorComponents[8] = { startColorComponents[0], startColorComponents[1], startColorComponents[2], startColorComponents[3], endColorComponents[0], endColorComponents[1], endColorComponents[2], endColorComponents[3] }; CGFloat colorIndices[2] = { 0.0f, 1.0f }; CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, (const CGFloat *)&colorComponents, (const CGFloat *)&colorIndices, 2); CGColorSpaceRelease(colorSpace); CGPoint startPoint, endPoint; startPoint = CGPointMake(120.0f, 260.0f); endPoint = CGPointMake(120.0f, 220.0f); CGContextRef currentContext = UIGraphicsGetCurrentContext(); CGContextSaveGState(currentContext); CGContextDrawLinearGradient(currentContext, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CGGradientRelease(gradient); CGContextRestoreGState(currentContext);); CGGradientRelease(gradient); CGContextRestoreGState(currentContext);
这段代码和上面的基本相同,有两处区别,一是start和end坐标不同,这回两个点连线之后时候与屏幕垂直的一条短线,高度并没有达到整个屏幕;第二个是使用了参数kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation。
我们看看效果
现在我将CGContextDrawLinearGradient第四个参数分别使用kCGGradientDrawsBeforeStartLocation,kCGGradientDrawsAfterEndLocation和0,你们就能看出区别来了。注意start左边在end的下方。
简单吧:)