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);elsestartAngle = 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;
}

视图效果如下图:

IOS 仿Android色轮代码相关推荐

  1. android自定义吐司通知,IOS 仿Android吐司提示框的实例(分享)

    直接上代码 #import @interface ShowToastView : UIView +(void)showToastView:(UIView *)uiview WithMessage:(N ...

  2. ios编译与android编译区别是什么,为iOS和Android编译C ++代码(XCode)。 这是真的吗?...

    你绝对可以在iOS和Android上使用C ++. 我已经为两者编写了自己的游戏引擎. Xcode是iOS的常规IDE,本身支持"Objective-C ++"开发(编译器支持Ob ...

  3. 适用于ios和android,适用于iOS和Android的OpenGL ES差异

    我有一个适用于iOS和 Android的OpenGL ES应用程序.大多数代码是很久以前由另一个人编写的,现在我必须维护它. OpenGL的使用看起来相当简单(游戏是2D,只使用纹理精灵以简单的方式) ...

  4. iOS 仿支付宝密码支付

    代码地址如下: http://www.demodashi.com/demo/11484.html 一.准备工作 xcode 主要实现输入密码的时候不可见 二.程序实现 实现思路怎样 在支付宝输入密码的 ...

  5. 转载关于通过判断浏览器的userAgent,用正则来判断是否是ios和Android客户端

    声明:本文为转载文章  中间部分穿插文字为本人查阅其他资料所得,其目的只是为了加强记忆和方便阅读,并无它意. 通过判断浏览器的userAgent,用正则来判断是否是ios和Android客户端.代码如 ...

  6. JS判断客户端是否是iOS或者Android手机移动端

    通过判断浏览器的userAgent,用正则来判断是否是ios和Android客户端.代码如下: <script type="text/javascript"> var ...

  7. JS判断手机是否是iOS或者Android

    JS判断客户端是否是iOS或者Android 第一种:通过判断浏览器的userAgent,用正则来判断是否是ios和Android客户端.代码如下: var u = navigator.userAge ...

  8. 移动端实现swiper轮播的图片视频播放video,仿淘宝商品详情的视频播放(兼容ios和android)

    前段时间项目里需要,实现仿淘宝图片视频切换的功能,在网上找了很久,根据网上所收集的信息,最后整合实现项目需求,这里兼容了ios和android,直接拿来用即可,这里是用来记录学习使用的,大家有什么问题 ...

  9. 高仿书旗小说 Flutter版,支持iOS、Android

    高仿书旗小说 Flutter版,支持iOS/Android Github地址 github.com/huanxsd/flu- screen shot for iOS screen shot for A ...

最新文章

  1. 运行webpack-dev-srerver 端口占用错误及解决办法
  2. 团体程序设计天梯赛-练习集-L1-039. 古风排版
  3. 网络对抗技术 实验报告 三
  4. 电信笔试c语言编程,华工电信院电子与通信工程 923复试面试,笔试考什么?复试真题...
  5. 性能测试—前端性能1
  6. 经验 | 深度学习中从基础综述、论文笔记到工程经验、训练技巧
  7. ( 转)Hibernate常用API
  8. 完全复制一个dict_关于Excel工作表复制里面列宽的介绍
  9. 关于Aspose对于Word操作的一些扩展及思考
  10. Java基础-学习笔记(六)——类的封装性
  11. 【Caffe】caffe框架讲解,解析修改caffemodel与prototxt
  12. Github上托管项目
  13. 如何高效的自学编程(新手篇)
  14. C++产生随机数字最全教程
  15. html命名锚记链接失败,命名锚记(设置命名锚记超级链接)
  16. 3D 打印切片软件 CuraEngine 介绍
  17. gitlab安装及配置
  18. Grep命令常见用法
  19. 50 条有趣的 Python 一行代码
  20. 漫画|微信群聊的程序员们

热门文章

  1. FlurryAnalytics for ios
  2. Java-Fizzbuzz
  3. 聚焦数字经济 共商数字机遇 中科物联与圣笛数控再添新伙伴
  4. “爱你千百遍” 消息连发
  5. angularJS的复选框
  6. 显示2012年之前的月份日历代码
  7. 基于element-ui插件设置页脚
  8. 破解WinRAR4.20 64位
  9. JS实现鼠标移上去图片停止滚动移开恢复滚动效果
  10. Android NDK 编译和 Crash 问题集合