iOS Quartz2D 渐变图形 CGGradient CGShading
Posted HeathHsia
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS Quartz2D 渐变图形 CGGradient CGShading相关的知识,希望对你有一定的参考价值。
最近在学习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>
以上是关于iOS Quartz2D 渐变图形 CGGradient CGShading的主要内容,如果未能解决你的问题,请参考以下文章
iOS 2D绘图 (Quartz2D)之阴影和渐变(shadow,Gradient)