IOS 仿Android色轮代码
在android中做色轮相对比较容易,因为Android中有一个角度渐变着色器函数SweepGradient能够很轻松的完成圆环的环形着色绘制工作,在利用Paint的setShader方法将创建的着色器设置到画笔里,然后直接就可以画出环形渐变效果了,然而不幸的是IOS里面没有类似的方法可以实现这一点。目前网上提到的大多都是:
1、使用的是UIBezierPath曲线+CAGradientLayer线形渐变来模拟的,这种做法问题很多,做出来的效果很差;
2、另外网上也提到了另外一种方法,那就是用一张七彩色的环形渐变图片来进行圆环路径裁剪实现,这个做出来的效果完全实现了Android一样的色轮选择样式,但是就是有一个问题,需要附带一个大的背景图片。
本文中的实现主要参考了第二种方法来实现的,唯一的不同是七彩渐变背景图在这里非使用了一张固定的背景图片,而是参考了网上比较流行的ios颜色选择器MSColorPicker中的HSL颜色背景绘制方法实现的,代码全部都做了注释,后面就不在讲述具体过程。完整代码如下:
首先是颜色工具类USColor。主要用于HSB与RGB之间的转换。
1、USColor.h头文件
//
// USColor.h
// BluetoothLight
//
// Created by Apple on 2021/1/14.
// Copyright © 2021 sbkj. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef struct { CGFloat red, green, blue, alpha; } USRGB;
typedef struct { CGFloat hue, saturation, brightness, alpha; } USHSB;
extern USHSB USRGBToHsb(USRGB rgb);
extern USRGB USHsbToRGB(USHSB hsb);
/**
*Hsb色彩空间转UIColor对象
*@param hsb Hsb色彩空间
*@return UIColor指针
*/
extern UIColor * USHsbToUIColor(USHSB hsb);
2、USColor.w objectiv-c文件
//
// USColor.m
// BluetoothLight
//
// Created by Apple on 2021/1/14.
// Copyright © 2021 sbkj. All rights reserved.
//
#import "USColor.h"
#pragma mark -rgb颜色转hsb
extern USHSB USRGBToHsb(USRGB rgb){
USHSB hsb = { 0.0f, 0.0f, 0.0f, 0.0f };
if(rgb.red<0)
rgb.red=0.0;
else if(rgb.red>255.0)
rgb.red=255.0;
if(rgb.green<0)
rgb.green=0;
else if(rgb.green>255.0)
rgb.green=255.0;
if(rgb.blue<0)
rgb.blue=0;
else if(rgb.blue>255.0)
rgb.blue=255.0;
float r=rgb.red/255.0;
float g=rgb.green/255.0;
float b=rgb.blue/255.0;
float max=MAX(r, MAX(g, b)); //返回最大值
float min=MIN(r, MIN(g, b)); //返回最小值
float difference=max-min; //得到最大值与最小值的差
//float hue,saturation,brightness;
if(max==min){
hsb.hue=0;
}else if(max==r){
int c =(int)((g-b)/ difference)*1000; //为保证精度,将计算的值放大1000倍
hsb.hue=c%6000;//将6放大1000倍
}else if(max==g){
hsb.hue=(b-r)/difference;
}else{
hsb.hue=(r-g)/difference;
}
hsb.hue*=60;
if(hsb.hue<0)
hsb.hue+=360;
hsb.brightness=max;
hsb.saturation=(hsb.brightness==0?0:(difference/hsb.brightness));
hsb.saturation*=100; //放大100倍
hsb.brightness*=100; //放大100倍
hsb.alpha=rgb.alpha;
return hsb;
}
#pragma mark -hsb颜色转rgb
extern USRGB USHsbToRGB(USHSB hsb){
//NSLog(@"色相: %f", hsb.hue);
USRGB rgb={0.0f,0.0f,0.0f,0.0f};
if(hsb.hue<0)
hsb.hue=0.0;
else if(hsb.hue>=360)
hsb.hue=359.0;
if(hsb.saturation<0)
hsb.saturation=0.0;
else if(hsb.saturation>100)
hsb.saturation=100.0;
if(hsb.brightness<0)
hsb.brightness=0.0;
else if(hsb.brightness>100)
hsb.brightness=100.0;
hsb.saturation/=100;
hsb.brightness/=100;
float C=hsb.brightness*hsb.saturation;
float hh=hsb.hue/60;
int intHH=(int)hh;
float X=C*(1-ABS(intHH%2+(hh-intHH)-1));
float M=hsb.brightness-C;
if(hh>=0 && hh<1){
rgb.red=C;
rgb.green=X;
}else if(hh>=1 && hh<2){
rgb.red=X;
rgb.green=C;
}else if(hh>=2 && hh<3){
rgb.green=C;
rgb.blue=X;
}else if(hh>=3 && hh<4){
rgb.green=X;
rgb.blue=C;
}else if(hh>=4 && hh<5){
rgb.red=X;
rgb.blue=C;
}else{
rgb.red=C;
rgb.blue=X;
}
rgb.red+=M;
rgb.green+=M;
rgb.blue+=M;
rgb.red*=255.0;
rgb.green*=255.0;
rgb.blue*=255.0;
rgb.alpha=hsb.alpha;
return rgb;
}
#pragma mark -hsb颜色转UIColor
extern UIColor * USHsbToUIColor(USHSB hsb){
USRGB rgb=USHsbToRGB(hsb);
return [UIColor colorWithRed:rgb.red/255.0f green:rgb.green/255.0f blue:rgb.blue/255.0f alpha:rgb.alpha];
}
接下来是色轮绘制的完整代码:
1、USColorPickerView.h头文件
//
// USColorPickerView.h
//
// Created by Apple on 2021/1/14.
// Copyright © 2021 sbkj. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "USColor.h"
@interface USColorPickerView : UIControl
@property (nonatomic, readwrite) CGFloat ringWidth; //绘制线宽度
@property (readwrite, getter=isChecked)BOOL checked; //复选状态
@property (nonatomic, readwrite,setter=setImige:)UIImage * _Nullable imige; //中心圆内图标
@property (nonatomic, setter=setCurrentColor:)USHSB currentColor; //当前颜色
@property (nonatomic,setter=setHue:)CGFloat hue; //色相
@property(nonatomic,setter=setSaturation:)CGFloat saturation; //饱和度
@property(nonatomic,setter=setBrightness:)CGFloat brightness; //亮度
@property(null_resettable, nonatomic, strong) UIColor *tintColor; //图片着色
@property(readwrite,getter=isEnabledClick)BOOL enabledClick; //启用中心按钮单击事件
@end
2、USColorPickerView.m objectiv-c文件
//
// USColorPickerView.m
//
// Created by Apple on 2021/1/14.
// Copyright © 2021 sbkj. All rights reserved.
//
#import "USColorPickerView.h"
角度转弧度
//static inline double DegreesToRadians(double angle) {
// return M_PI * angle / 180.0;
//}
弧度转角度
//static inline double RadiansToDegrees(double angle) {
// return angle * 180.0 / M_PI;
//}
static inline CGPoint CGPointCenterRadiusAngle(CGPoint c, double r, double a) {
return CGPointMake(c.x + r * cos(a), c.y + r * sin(a));
}
static inline CGFloat AngleBetweenPoints(CGPoint a, CGPoint b, CGPoint c) {
return atan2(a.y - c.y, a.x - c.x) - atan2(b.y - c.y, b.x - c.x);
}
@interface USColorPickerView()
@property (nonatomic, assign) CGFloat startAngle; //开始角度
@property (nonatomic, assign) CGFloat cutoutAngle; //终止角度
@property(assign,nonatomic) CGPoint centerRing; //圆环的圆心坐标
@property (nonatomic, assign) CGFloat radiusRing; //圆环半径
@property (assign, nonatomic) CGPoint handcenterPoint; //滑块圆心坐标
@property (nonatomic, assign) CGFloat handleOutSideRadius; //外圆环半径
@property (nonatomic, assign) CGFloat handleInSideRadius; //内圆环半径
@property (nonatomic, assign)CGImageRef imageRef;
@property BOOL startTouch;
@property BOOL centerDown;
@end
@implementation USColorPickerView
- (instancetype)init{
return [self initWithFrame:CGRectZero] ;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if(self)
{
[self viewInitialize];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self viewInitialize];
}
return self;
}
#pragma mark -视图初始化
- (void)viewInitialize{
_tintColor=nil;
_startAngle = 0.f;
_cutoutAngle = 0.f;
_ringWidth = CGRectGetWidth(self.frame) / 16;
_currentColor.hue=0;
_currentColor.saturation=100;
_currentColor.brightness=100;
_currentColor.alpha=1.0f;
_handleOutSideRadius = _ringWidth - 2;
_handleInSideRadius = _handleOutSideRadius / 2;
_checked=NO;
_imige=nil;
_startTouch=NO;
_centerDown=NO;
_enabledClick=YES;
_imageRef=[self createColorWheelImageRef:CGRectGetMidX(self.bounds)];
}
#pragma mark -触摸开始事件
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//5.遍历
for(int i=0;i<touches.count;i++){
UITouch * touch =[touches anyObject];
CGPoint location = [touch locationInView:self];
if([self pointRing:location]){
//NSLog(@"触摸开始: %@", @"触摸点在圆环上面");
if(![self pointInsideHandle:location]){ //点不在滑块上
[self drawWithLocation:location];
//NSLog(@"触摸开始: %@", @"触摸点在滑块上面");
}
_startTouch=YES; //标识为开始触摸
break;
}else if([self pointCenterButton:location]){
_centerDown=YES;
break;
}else{
if([self pointInsideHandle:location]){ //点在滑块上
_startTouch=YES;
break;
}
}
}
}
#pragma mark -触摸移动事件
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
if(_startTouch){ //如果标示为开始触摸,执行触摸移动
for(int i=0;i<touches.count;i++){
UITouch * touch =[touches anyObject];
CGPoint location = [touch locationInView:self];
[self drawWithLocation:location];
if(i>0)
break;
}
}
}
#pragma mark -触摸结束事件
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self touchesEnd:touches withEvent:event]; //触摸结束处理
}
#pragma mark -触摸取消事件
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self touchesEnd:touches withEvent:event];//触摸结束处理
}
#pragma mark -触摸结束
-(void)touchesEnd:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
if(_startTouch){
for(int i=0;i<touches.count;i++){
UITouch * touch =[touches anyObject];
CGPoint location = [touch locationInView:self];
[self drawWithLocation:location];
if(i>0)
break;
}
//发送至发生改变事件
[self sendActionsForControlEvents:UIControlEventValueChanged];
}else if(_centerDown && _enabledClick){
//发送触摸在控件范围内抬起事件
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
_centerDown=NO;
_startTouch=NO;
}
#pragma mark -检测触摸点是否在滑动块中
/**
* 检测触摸点是否在滑动块中
* @param point 触摸点坐标
*/
- (BOOL)pointInsideHandle:(CGPoint)point{
CGPoint handleCenter = CGPointMake(_handcenterPoint.x, self.bounds.size.width- _handcenterPoint.y) ;
CGFloat handleRadius = _handleOutSideRadius + 30;
CGRect handleRect = CGRectMake(handleCenter.x - handleRadius, handleCenter.y - handleRadius, handleRadius * 2, handleRadius * 2);
return CGRectContainsPoint(handleRect, point);
}
#pragma mark -检测点是否在圆环上
/**
*检测点是否在圆环上
*@param point 触摸点坐标
*/
-(BOOL)pointRing:(CGPoint)point{
//获取当前点与圆心坐标点偏移量
float centralOffset=sqrt(pow(point.x-_centerRing.x, 2)+pow(point.y-_centerRing.y, 2));
float radius = CGRectGetMidX(self.bounds) - self.ringWidth / 2 ;
float lineW=self.ringWidth/2;
return centralOffset>=radius-self.ringWidth && centralOffset<=radius+lineW;
}
#pragma mark -检测点是否在中心按钮上
-(BOOL)pointCenterButton:(CGPoint)point{
//获取当前点与圆心坐标点偏移量
float centralOffset=sqrt(pow(point.x-_centerRing.x, 2)+pow(point.y-_centerRing.y, 2));
float radius=(CGRectGetMidX(self.bounds) - self.ringWidth*2)/2 ; //中心圆半径
return centralOffset<=radius;
}
#pragma mark -绘制移动坐标后的内容
/**
* 绘制移动坐标后的内容
* @param location 触摸点坐标
*/
- (void)drawWithLocation:(CGPoint)location {
CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
CGFloat radius = CGRectGetMidX(self.bounds) - self.ringWidth / 2;
CGFloat startAngle = _startAngle;
if (startAngle < 0)
startAngle = fabs(startAngle);
else
startAngle = 360.f - startAngle;
CGPoint startPoint = CGPointCenterRadiusAngle(center, radius, DegreesToRadians(startAngle));//DegreesToRadians(startAngle)将开始角转换为弧度
CGFloat angle = RadiansToDegrees(AngleBetweenPoints(location, startPoint, center));//将弧度转位角度
if (angle < 0) angle += 360.f;//将角度位负数转为正数角度
angle = angle - _cutoutAngle / 2.f;
_currentColor.hue=angle+90;
if(_currentColor.hue>360)
_currentColor.hue-=360;
_hue=_currentColor.hue;
NSLog(@"角度: %f", _currentColor.hue);
//self.progress = angle / (360.f - _cutoutAngle);
//(原始代码不调用该方法也能触发重绘事件,现必须动用才能重绘,不知道问题在上面地方)
[self setNeedsDisplay];
}
#pragma mark -绘制内容
-(void)drawRect:(CGRect)rect {
//得到当前颜色
USRGB rgb=USHsbToRGB(_currentColor);
// 绘制代码
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0.0, self.bounds.size.height); //改变画布位置(0,0位置移动到此处)
CGContextScaleCTM(context, 1.0, -1.0);
//滑动条中心位置
_centerRing = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
//滑动条半径
_radiusRing = CGRectGetMidX(self.bounds) - self.ringWidth / 2 - self.handleOutSideRadius ;
CGFloat changeAngle = self.cutoutAngle / 2.0;
//滑动条起始角度
CGFloat arcStartAngle = DegreesToRadians(self.startAngle + 360.0 - changeAngle);
//滑动条结束角度
CGFloat arcEndAngle = DegreesToRadians(self.startAngle + changeAngle);
//滑块弧度
CGFloat progressAngle = DegreesToRadians(360.f - self.cutoutAngle)*((_currentColor.hue-90)/360);
// NSLog(@"滑块角度: %f", progressAngle);
// 把当前上下文状态保存在栈中,防止以下操作影响圆形按钮的绘制
CGContextSaveGState(context);
CGContextSetLineWidth(context, self.ringWidth);
CGContextAddArc(context, _centerRing.x, _centerRing.y, _radiusRing, arcStartAngle, arcEndAngle, 1);
CGContextSetLineCap(context, kCGLineCapRound);
//将context中的路径替换成路径的描边版本,使用参数context去计算路径(即创建新的路径是原来路径的描边)。用恰当的颜色填充得到的路径将产生类似绘制原来路径的效果。你可以像使用一般的路径一样使用它。例如,你可以通过调用CGContextClip去剪裁这个路径的描边
CGContextReplacePathWithStrokedPath(context);
// 剪裁路径
CGContextClip(context);
// 绘制角度渐变
// UIImage * gradientImg= [UIImage imageNamed:@"gradient.jpg"];
// CGContextDrawImage(context, self.bounds, gradientImg.CGImage);
CGContextDrawImage(context, self.bounds, _imageRef);
// 把保存在栈中的上下文状态取出来,恢复。上面那段代码设置的样式不会影响其他
CGContextRestoreGState(context);
//******************************画中心圆***************************************/
float radius=(CGRectGetMidX(self.bounds) - self.ringWidth*2)/2 ; //中心圆半径
CGRect frame = CGRectMake(_centerRing.x-radius, _centerRing.y-radius, radius*2 , radius*2 );
//---------------中心圆向外扩散特效,根据不同色彩亮度扩散半径不同(径向渐变)-------------------//
if(_checked){
//用中心圆半径+中心圆到圆环内侧的宽度/100*亮度值得到扩散圆的半径
float diffusionRadius=radius+((_radiusRing-radius-self.ringWidth/2)/100)*_currentColor.brightness;
// NSLog(@"半径: %f", diffusionRadius);
// 创建起点和终点颜色分量的数组
CGFloat colors[8] ={
rgb.red/255, rgb.green/255, rgb.blue/255, 1.0f,//开始颜色(r,g,b,alpha)
rgb.red/255, rgb.green/255, rgb.blue/255, 0.0f//结束颜色
};
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();// 创建色彩空间对象
//形成梯形,渐变的效果
CGGradientRef gradient = CGGradientCreateWithColorComponents(space, colors, NULL, 2);
// 起点颜色起始圆心
CGPoint start = CGPointMake(_centerRing.x, _centerRing.y);
// 终点颜色起始圆心
CGPoint end = CGPointMake(_centerRing.x, _centerRing.y);
// 起点颜色圆形半径
CGFloat startRadius = 0.0f;
// 终点颜色圆形半径
CGFloat endRadius = diffusionRadius;
// 获取上下文
CGContextRef graCtx = UIGraphicsGetCurrentContext();
// 创建一个径向渐变
CGContextDrawRadialGradient(graCtx, gradient, start, startRadius, end, endRadius, 0);
//释放资源
CGGradientRelease(gradient);
gradient=NULL;
CGColorSpaceRelease(space);
//------------------中心实心圆---------------------//
CGContextAddEllipseInRect(context, frame);
[[UIColor colorWithRed:rgb.red/255 green:rgb.green/255 blue:rgb.blue/255 alpha:1.0f] set];
CGContextFillPath(context);
}
//--------------中心画圆的边框---------------//
radius-=2;
//frame = CGRectMake(_centerRing.x-radius, _centerRing.y-radius, radius*2 , radius*2 );
CGContextAddEllipseInRect(context, frame);
CGContextSetLineWidth(context, 2);
[[UIColor whiteColor] set];
CGContextStrokePath(context);
if(_imige!=nil){
float imgsize=radius/2; //图标大小
UIImage *dwgImige; //待绘制的图片
if(_tintColor!=nil){ //图片渲染成知道颜色
dwgImige=[self tintImageWithColor:_imige tintColor:_tintColor];
}else{
dwgImige=_imige;
}
[dwgImige drawInRect:CGRectMake(_centerRing.x-imgsize, _centerRing.y-imgsize, imgsize*2, imgsize*2)];
}
//-----------------绘制圆形可拖动按钮------------------//
[[UIColor whiteColor] set];
CGContextSetShadow(context, CGSizeMake(0.0, 0.0), 1.0);
//CGContextSetLineWidth(context, self.handleOutSideRadius);
CGPoint handle = CGPointCenterRadiusAngle(_centerRing, _radiusRing, arcStartAngle - progressAngle);
_handcenterPoint = handle;//将滑块圆心保存
CGContextSetLineWidth(context, 2);
CGContextAddArc(context, handle.x, handle.y, self.handleOutSideRadius / 2+1, 0, DegreesToRadians(360), 1);
CGContextStrokePath(context);
if(self.startTouch==YES){
USHSB ushsb={_currentColor.hue,100.0,100.0,0.4};
[USHsbToUIColor(ushsb) set]; //这里应该要用当前角度指向的颜色
CGContextSetShadow(context, CGSizeMake(0.0, 0.0), 1.0);
CGContextSetLineWidth(context, self.handleOutSideRadius);
CGPoint handle_1 = CGPointCenterRadiusAngle(_centerRing, _radiusRing, arcStartAngle - progressAngle);
_handcenterPoint = handle_1;//将滑块圆心保存
CGContextAddArc(context, handle_1.x, handle_1.y, self.handleOutSideRadius + 1, 0, DegreesToRadians(360), 1);
CGContextStrokePath(context);
}
}
#pragma mark -设置当前颜色值
/**
*@param hsbColor 当前颜色值
*/
-(void)setCurrentColor:(USHSB)hsbColor{
_currentColor=hsbColor;
_hue=_currentColor.hue;
_saturation=_currentColor.saturation;
_brightness=_currentColor.brightness;
[self setNeedsDisplay]; //重会
}
#pragma mark -设置中心图像
-(void)setImige:(UIImage*)imige{
_imige=imige;
[self setNeedsDisplay]; //重会
}
#pragma mark -设置圆环宽度
-(void)setRingWidth:(CGFloat)ringWidth{
_ringWidth=ringWidth;
[self setNeedsDisplay]; //重会
}
#pragma mark -设置中心图像渲染颜色
-(void)setTintColor:(UIColor *)tintColor{
_tintColor=tintColor;
[self setNeedsDisplay]; //重会
}
#pragma mark -设置当前色相(0-360之间)
-(void)setHue:(CGFloat)hue{
_hue=hue;
_currentColor.hue=hue;
[self setNeedsDisplay]; //重会
}
#pragma mark -设置当前饱和度
-(void)setSaturation:(CGFloat)saturation{
_saturation=saturation;
_currentColor.saturation=saturation;
[self setNeedsDisplay]; //重会
}
#pragma mark -设置当前亮度
-(void)setBrightness:(CGFloat)brightness{
_brightness=brightness;
_currentColor.brightness=brightness;
[self setNeedsDisplay]; //重会
}
#pragma mark -创建HSB色轮图像
/**
*创建HSB色轮图像
*@param size 想要创建的色轮图像大小
*/
-(UIImage *)createColorWheelImage:(CGFloat)size {
return [UIImage imageWithCGImage: [self createColorWheelImageRef:size]];
}
#pragma mark -创建图像色彩空间
-(CGImageRef)createColorWheelImageRef:(CGFloat)size{
CFMutableDataRef bitmapData = CFDataCreateMutable(NULL, 0);
CFDataSetLength(bitmapData, size * size * 4);
[self ms_colorWheelBitmap:CFDataGetMutableBytePtr(bitmapData) withSize:CGSizeMake(size, size)];
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(bitmapData);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef imageRef = CGImageCreate(size, size, 8, 32, size * 4, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, dataProvider, NULL, 0, kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colorSpace);
CFRelease(bitmapData);
return imageRef;
}
#pragma mark -色轮位图
/**
* 色轮位图
* @param bitmap 色轮位图缓冲区指针
* @param size 色轮位图大小
*/
- (void)ms_colorWheelBitmap:(out UInt8 *)bitmap withSize:(CGSize)size{
for (NSUInteger y = 0; y < size.width; y++) {
for (NSUInteger x = 0; x < size.height; x++) {
CGFloat hue, saturation, a = 0.0f;
[self ms_colorWheelValueWithPosition:CGPointMake(x, y) imageSize:size hue:&hue saturation:&saturation];
hue=hue*360.0f+90.0f;
if(hue>360)
hue-=360;
USRGB rgb = { 0.0f, 0.0f, 0.0f, 0.0f };
if (saturation < 1.0) {
// 园的边缘反锯齿
if (saturation > 0.99) {
a = (1.0 - saturation) * 100;
} else {
a = 1.0;
}
USHSB hsb={hue,100,100,a};
rgb=USHsbToRGB(hsb);
}
NSInteger i = 4 * (x + y * size.width);
bitmap[i] = rgb.red ;//* 0xff;
bitmap[i + 1] = rgb.green ;//* 0xff;
bitmap[i + 2] = rgb.blue ;//* 0xff;
bitmap[i + 3] = rgb.alpha * 0xff;
}
}
}
#pragma mark -计算指定点色相及饱和度
/**
*计算指定点色相及饱和度
*@param position 要计算色相的点
*@param size 图像大小
*@param hue 需要返回的色相地址
*@param saturation 饱和度地址
*/
- (void)ms_colorWheelValueWithPosition:(CGPoint)position imageSize:(CGSize)size hue:(out CGFloat *)hue saturation:(out CGFloat *)saturation{
CGRect rect = CGRectMake(0, 0, size.width, size.height);//得到图像边界区域
NSInteger c =CGRectGetWidth(rect) / 2;//用图像边界区域替换当前视图编辑区域self.bounds;
CGFloat dx = (float)(position.x - c) / c;
CGFloat dy = (float)(position.y - c) / c;
CGFloat d = sqrtf((float)(dx * dx + dy * dy));
*saturation = d;
if (d == 0) {
*hue = 0;
} else {
*hue = acosf((float)dx / d) / M_PI / 2.0f;
if (dy < 0) {
*hue = 1.0 - *hue;
}
}
}
#pragma mark -图像渲染
/**
*@param image 要进行渲染的原始图像
*@param tintColor 用于对图像进行渲染的颜色
*@return 返回新的图像
*/
- ( UIImage *) tintImageWithColor:(UIImage *)image tintColor:(UIColor *)tintColor{
UIGraphicsBeginImageContextWithOptions ( image . size , NO , [[ UIScreen mainScreen ] scale ]);
CGContextRef context = UIGraphicsGetCurrentContext ();
CGContextTranslateCTM (context, 0 , image . size . height );
CGContextScaleCTM (context, 1.0 , - 1.0 );
CGRect rect = CGRectMake ( 0 , 0 , image . size . width , image . size . height );
CGContextSetBlendMode (context, kCGBlendModeNormal );
CGContextDrawImage (context, rect, image . CGImage );
CGContextSetBlendMode (context, kCGBlendModeSourceIn );
[tintColor setFill ];
CGContextFillRect (context, rect);
UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext ();
UIGraphicsEndImageContext ();
return coloredImage;
}
@end
在这里主要要注意的是背景图的创建,建议定义一个全局变量来存储背景图数据。可以在- (void)viewInitialize{}中初始化创建,后面直接使用或在绘制的时候做一个判断,如果背景图没有创建,先创建然后再绘制到视图中,不建议将背景图数据存储变量定义为临时变量,每次绘制都创建。另外需要注意的是因为我的项目中已经包含了DegreesToRadians及RadiansToDegrees两个函数,故在USColorPickerView.m中已经将这两个方法注释掉了,如果你们工程中未包含DegreesToRadians及RadiansToDegrees两个函数,请将USColorPickerView.m顶部的两个被注释掉两个方法修改改为如下:
// 角度转弧度
static inline double DegreesToRadians(double angle) {
return M_PI * angle / 180.0;
}
// 弧度转角度
static inline double RadiansToDegrees(double angle) {
return angle * 180.0 / M_PI;
}
视图效果如下图: