Created
November 21, 2016 03:54
-
-
Save luowei/c680dcfb9d19672232125a7c02a4ef30 to your computer and use it in GitHub Desktop.
UIColor OC扩展
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@interface UIColor (CrossFade) | |
/** | |
* Fades between firstColor and secondColor at the specified ratio: | |
* | |
* @ ratio 0.0 - fully firstColor | |
* @ ratio 0.5 - halfway between firstColor and secondColor | |
* @ ratio 1.0 - fully secondColor | |
* | |
*/ | |
+ (UIColor *)colorForFadeBetweenFirstColor:(UIColor *)firstColor | |
secondColor:(UIColor *)secondColor | |
atRatio:(CGFloat)ratio; | |
/** | |
* Same as above, but allows turning off the color space comparison | |
* for a performance boost. | |
*/ | |
+ (UIColor *)colorForFadeBetweenFirstColor:(UIColor *)firstColor secondColor:(UIColor *)secondColor atRatio:(CGFloat)ratio compareColorSpaces:(BOOL)compare; | |
//根据比例与alpha值得到一个过渡色 | |
+ (UIColor *)colorBetweenFirstColor:(UIColor *)firstColor secondColor:(UIColor *)secondColor atRatio:(CGFloat)ratio withAlpha:(CGFloat)alpha; | |
/** | |
* An array of [steps] colors starting with firstColor, continuing with linear interpolations | |
* between firstColor and lastColor and ending with lastColor. | |
*/ | |
+ (NSArray *)colorsForFadeBetweenFirstColor:(UIColor *)firstColor | |
lastColor:(UIColor *)lastColor | |
inSteps:(NSUInteger)steps; | |
/** | |
* An array of [steps] colors starting with firstColor, continuing with interpolations, as specified | |
* by the equation block, between firstColor and lastColor and ending with lastColor. The equation block | |
* must take a float as an input, and return a float as an output. Output will be santizied to be between | |
* a ratio of 0.0 and 1.0. Passing nil for the equation results in a linear relationship. | |
*/ | |
+ (NSArray *)colorsForFadeBetweenFirstColor:(UIColor *)firstColor | |
lastColor:(UIColor *)lastColor | |
withRatioEquation:(float (^)(float input))equation | |
inSteps:(NSUInteger)steps; | |
/** | |
* Convert UIColor to RGBA colorspace. Used for cross-colorspace interpolation. | |
*/ | |
+ (UIColor *)colorConvertedToRGBA:(UIColor *)colorToConvert; | |
/** | |
* Creates a CAKeyframeAnimation for the given key path, duration, and first/last colors that can be | |
* applied to an appropriate CALayer property (i.e. backgroundColor). See the demo for example usage. | |
*/ | |
+ (CAKeyframeAnimation *)keyframeAnimationForKeyPath:(NSString *)keyPath | |
duration:(NSTimeInterval)duration | |
betweenFirstColor:(UIColor *)firstColor | |
lastColor:(UIColor *)lastColor; | |
/** | |
* Same as above, but allows setting a ratio equation (for non-linear transitions between colors) and | |
* the number of steps to calculate. Decreasing steps may improve performance as it decreases the number | |
* of cross-fade calculations necessary. | |
*/ | |
+ (CAKeyframeAnimation *)keyframeAnimationForKeyPath:(NSString *)keyPath | |
duration:(NSTimeInterval)duration | |
betweenFirstColor:(UIColor *)firstColor | |
lastColor:(UIColor *)lastColor | |
withRatioEquation:(float (^)(float))equation | |
inSteps:(NSUInteger)steps; | |
@end | |
//======= HexValue ======= | |
@interface UIColor (HexValue) | |
+ (UIColor *)colorWithRGBAString:(NSString *)RGBAString; | |
+ (UIColor *)colorWithHexString:(NSString *)hex; | |
//从UIColor得到RGBA字符串 | |
+(NSString *)rgbaStringFromUIColor:(UIColor *)color; | |
+(NSString *)hexValuesFromUIColor:(UIColor *)color; | |
+ (UIColor *)colorWithHex:(uint)hex alpha:(CGFloat)alpha; | |
@end | |
//------- Implamentation -------- | |
@implementation UIColor (CrossFade) | |
+ (UIColor *)colorForFadeBetweenFirstColor:(UIColor *)firstColor | |
secondColor:(UIColor *)secondColor | |
atRatio:(CGFloat)ratio { | |
return [self colorForFadeBetweenFirstColor:firstColor secondColor:secondColor atRatio:ratio compareColorSpaces:YES]; | |
} | |
+ (UIColor *)colorForFadeBetweenFirstColor:(UIColor *)firstColor secondColor:(UIColor *)secondColor atRatio:(CGFloat)ratio compareColorSpaces:(BOOL)compare { | |
// Eliminate values outside of 0 <--> 1 | |
ratio = MIN(MAX(0, ratio), 1); | |
// Convert to common RGBA colorspace if needed | |
if (compare) { | |
if (CGColorGetColorSpace(firstColor.CGColor) != CGColorGetColorSpace(secondColor.CGColor)) { | |
firstColor = [UIColor colorConvertedToRGBA:firstColor]; | |
secondColor = [UIColor colorConvertedToRGBA:secondColor]; | |
} | |
} | |
// Grab color components | |
const CGFloat *firstColorComponents = CGColorGetComponents(firstColor.CGColor); | |
const CGFloat *secondColorComponents = CGColorGetComponents(secondColor.CGColor); | |
// Interpolate between colors | |
CGFloat interpolatedComponents[CGColorGetNumberOfComponents(firstColor.CGColor)]; | |
for (NSUInteger i = 0; i < CGColorGetNumberOfComponents(firstColor.CGColor); i++) { | |
interpolatedComponents[i] = firstColorComponents[i] * (1 - ratio) + secondColorComponents[i] * ratio; | |
} | |
// Create interpolated color | |
CGColorRef interpolatedCGColor = CGColorCreate(CGColorGetColorSpace(firstColor.CGColor), interpolatedComponents); | |
UIColor *interpolatedColor = [UIColor colorWithCGColor:interpolatedCGColor]; | |
CGColorRelease(interpolatedCGColor); | |
return interpolatedColor; | |
} | |
//根据比例与alpha值得到一个过渡色 | |
+ (UIColor *)colorBetweenFirstColor:(UIColor *)firstColor secondColor:(UIColor *)secondColor atRatio:(CGFloat)ratio withAlpha:(CGFloat)alpha{ | |
// Eliminate values outside of 0 <--> 1 | |
ratio = MIN(MAX(0, ratio), 1); | |
// Convert to common RGBA colorspace if needed | |
if (CGColorGetColorSpace(firstColor.CGColor) != CGColorGetColorSpace(secondColor.CGColor)) { | |
firstColor = [UIColor colorConvertedToRGBA:firstColor]; | |
secondColor = [UIColor colorConvertedToRGBA:secondColor]; | |
} | |
// Grab color components | |
const CGFloat *firstColorComponents = CGColorGetComponents(firstColor.CGColor); | |
const CGFloat *secondColorComponents = CGColorGetComponents(secondColor.CGColor); | |
// Interpolate between colors | |
CGFloat interpolatedComponents[CGColorGetNumberOfComponents(firstColor.CGColor)]; | |
for (NSUInteger i = 0; i < CGColorGetNumberOfComponents(firstColor.CGColor); i++) { | |
if(i == 3){ | |
//把alpha通道值设置为alpha | |
interpolatedComponents[i] = alpha; | |
}else{ | |
interpolatedComponents[i] = firstColorComponents[i] * (1 - ratio) + secondColorComponents[i] * ratio; | |
} | |
} | |
// Create interpolated color | |
CGColorRef interpolatedCGColor = CGColorCreate(CGColorGetColorSpace(firstColor.CGColor), interpolatedComponents); | |
UIColor *interpolatedColor = [UIColor colorWithCGColor:interpolatedCGColor]; | |
CGColorRelease(interpolatedCGColor); | |
return interpolatedColor; | |
} | |
+ (NSArray *)colorsForFadeBetweenFirstColor:(UIColor *)firstColor | |
lastColor:(UIColor *)lastColor | |
inSteps:(NSUInteger)steps { | |
return [self colorsForFadeBetweenFirstColor:firstColor lastColor:lastColor withRatioEquation:nil inSteps:steps]; | |
} | |
+ (NSArray *)colorsForFadeBetweenFirstColor:(UIColor *)firstColor lastColor:(UIColor *)lastColor withRatioEquation:(float (^)(float input))equation inSteps:(NSUInteger)steps { | |
// Handle degenerate cases | |
if (steps == 0) | |
return nil; | |
if (steps == 1) | |
return [NSArray arrayWithObject:firstColor]; | |
if (steps == 2) | |
return [NSArray arrayWithObjects:firstColor, lastColor, nil]; | |
// Assume linear if no equation is passed | |
if (equation == nil) { | |
equation = ^(float input) { | |
return input; | |
}; | |
} | |
// Calculate step size | |
CGFloat stepSize = 1.0f / (steps - 1); | |
// Array to store colors in steps | |
NSMutableArray *colors = [[NSMutableArray alloc] initWithCapacity:steps]; | |
[colors addObject:firstColor]; | |
// Compute intermediate colors | |
CGFloat ratio = stepSize; | |
for (int i = 2; i < steps; i++) { | |
[colors addObject:[self colorForFadeBetweenFirstColor:firstColor secondColor:lastColor atRatio:equation(ratio)]]; | |
ratio += stepSize; | |
} | |
[colors addObject:lastColor]; | |
return colors; | |
} | |
+ (CAKeyframeAnimation *)keyframeAnimationForKeyPath:(NSString *)keyPath | |
duration:(NSTimeInterval)duration | |
betweenFirstColor:(UIColor *)firstColor | |
lastColor:(UIColor *)lastColor { | |
return [UIColor keyframeAnimationForKeyPath:keyPath | |
duration:duration | |
betweenFirstColor:firstColor | |
lastColor:lastColor | |
withRatioEquation:^float(float input) { | |
return input; | |
} inSteps:floorf(duration * 30.0f)]; | |
} | |
+ (CAKeyframeAnimation *)keyframeAnimationForKeyPath:(NSString *)keyPath | |
duration:(NSTimeInterval)duration | |
betweenFirstColor:(UIColor *)firstColor | |
lastColor:(UIColor *)lastColor | |
withRatioEquation:(float (^)(float input))equation | |
inSteps:(NSUInteger)steps { | |
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:keyPath]; | |
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; | |
animation.duration = duration; | |
NSArray *colorRefs = [[self colorsForFadeBetweenFirstColor:firstColor lastColor:lastColor withRatioEquation:equation inSteps:steps] valueForKeyPath:@"CCF_CGColor"]; | |
animation.values = colorRefs; | |
return animation; | |
} | |
#pragma mark - Helpers | |
+ (UIColor *)colorConvertedToRGBA:(UIColor *)colorToConvert; { | |
CGFloat red; | |
CGFloat green; | |
CGFloat blue; | |
CGFloat alpha; | |
// Convert color to RGBA with a CGContext. UIColor's getRed:green:blue:alpha: doesn't work across color spaces. Adapted from http://stackoverflow.com/a/4700259 | |
alpha = CGColorGetAlpha(colorToConvert.CGColor); | |
CGColorRef opaqueColor = CGColorCreateCopyWithAlpha(colorToConvert.CGColor, 1.0f); | |
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); | |
unsigned char resultingPixel[CGColorSpaceGetNumberOfComponents(rgbColorSpace)]; | |
CGContextRef context = CGBitmapContextCreate(&resultingPixel, 1, 1, 8, 4, rgbColorSpace, (CGBitmapInfo) kCGImageAlphaNoneSkipLast); | |
CGContextSetFillColorWithColor(context, opaqueColor); | |
CGColorRelease(opaqueColor); | |
CGContextFillRect(context, CGRectMake(0.f, 0.f, 1.f, 1.f)); | |
CGContextRelease(context); | |
CGColorSpaceRelease(rgbColorSpace); | |
red = resultingPixel[0] / 255.0f; | |
green = resultingPixel[1] / 255.0f; | |
blue = resultingPixel[2] / 255.0f; | |
return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; | |
} | |
- (id)valueForUndefinedKey:(NSString *)key { | |
if ([key isEqualToString:@"CCF_CGColor"]) { | |
return (id) self.CGColor; | |
} | |
return [super valueForUndefinedKey:key]; | |
} | |
@end | |
//========= HexValue ========== | |
@implementation UIColor (HexValue) | |
+ (UIColor *)colorWithRGBAString:(NSString *)RGBAString { | |
UIColor *color = nil; | |
NSArray *rgbaComponents = [RGBAString componentsSeparatedByString:@","]; | |
float RED = 0.0f; | |
float GREEN = 0.0f; | |
float BLUE = 0.0f; | |
float ALPHA = 0.0f; | |
//string like : 127,127,127 | |
if ([rgbaComponents count] == 3) { | |
RED = [(NSString*) rgbaComponents[0] floatValue]/255; | |
GREEN = [(NSString*) rgbaComponents[1] floatValue]/255; | |
BLUE = [(NSString*) rgbaComponents[2] floatValue]/255; | |
color = [UIColor colorWithRed:RED green:GREEN blue:BLUE alpha:1.0f]; | |
//string like : 127,127,127,255 | |
}else if ([rgbaComponents count] == 4) { | |
RED = [(NSString*) rgbaComponents[0] floatValue]/255; | |
GREEN = [(NSString*) rgbaComponents[1] floatValue]/255; | |
BLUE = [(NSString*) rgbaComponents[2] floatValue]/255; | |
ALPHA = [(NSString*) rgbaComponents[3] floatValue]/255; | |
color = [UIColor colorWithRed:RED green:GREEN blue:BLUE alpha:ALPHA]; | |
} | |
return color; | |
} | |
+(UIColor *)colorWithHexString:(NSString *)hexString { | |
if ([hexString length] != 6) { | |
return nil; | |
} | |
// Brutal and not-very elegant test for non hex-numeric characters | |
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^a-fA-F|0-9]" options:0 error:NULL]; | |
NSUInteger match = [regex numberOfMatchesInString:hexString options:NSMatchingReportCompletion range:NSMakeRange(0, [hexString length])]; | |
if (match != 0) { | |
return nil; | |
} | |
NSRange rRange = NSMakeRange(0, 2); | |
NSString *rComponent = [hexString substringWithRange:rRange]; | |
NSUInteger rVal = 0; | |
NSScanner *rScanner = [NSScanner scannerWithString:rComponent]; | |
[rScanner scanHexInt:((unsigned *)(&rVal))]; | |
float rRetVal = (float)rVal / 254; | |
NSRange gRange = NSMakeRange(2, 2); | |
NSString *gComponent = [hexString substringWithRange:gRange]; | |
NSUInteger gVal = 0; | |
NSScanner *gScanner = [NSScanner scannerWithString:gComponent]; | |
[gScanner scanHexInt:((unsigned *)(&rVal))]; | |
float gRetVal = (float)gVal / 254; | |
NSRange bRange = NSMakeRange(4, 2); | |
NSString *bComponent = [hexString substringWithRange:bRange]; | |
NSUInteger bVal = 0; | |
NSScanner *bScanner = [NSScanner scannerWithString:bComponent]; | |
[bScanner scanHexInt:((unsigned *)(&rVal))]; | |
float bRetVal = (float)bVal / 254; | |
return [UIColor colorWithRed:rRetVal green:gRetVal blue:bRetVal alpha:1.0f]; | |
} | |
+(NSString *)hexValuesFromUIColor:(UIColor *)color { | |
if (!color) { | |
return nil; | |
} | |
if (color == [UIColor whiteColor]) { | |
// Special case, as white doesn't fall into the RGB color space | |
return @"ffffff"; | |
} | |
CGFloat red; | |
CGFloat blue; | |
CGFloat green; | |
CGFloat alpha; | |
[color getRed:&red green:&green blue:&blue alpha:&alpha]; | |
int redDec = (int)(red * 255); | |
int greenDec = (int)(green * 255); | |
int blueDec = (int)(blue * 255); | |
NSString *returnString = [NSString stringWithFormat:@"%02x%02x%02x", (unsigned int)redDec, (unsigned int)greenDec, (unsigned int)blueDec]; | |
return returnString; | |
} | |
//从UIColor得到RGBA字符串 | |
+(NSString *)rgbaStringFromUIColor:(UIColor *)color { | |
if (!color) { | |
return nil; | |
} | |
if (color == [UIColor whiteColor]) { | |
// Special case, as white doesn't fall into the RGB color space | |
return @"255,255,255,255"; | |
} | |
CGFloat red; | |
CGFloat blue; | |
CGFloat green; | |
CGFloat alpha; | |
[color getRed:&red green:&green blue:&blue alpha:&alpha]; | |
int redDec = (int)(red * 255); | |
int greenDec = (int)(green * 255); | |
int blueDec = (int)(blue * 255); | |
int alphaDec = (int)(alpha * 255); | |
NSString *returnString = [NSString stringWithFormat:@"%d,%d,%d,%d", (unsigned int)redDec, (unsigned int)greenDec, (unsigned int)blueDec,(unsigned int)alphaDec]; | |
return returnString; | |
} | |
+ (UIColor *)colorWithHex:(uint)hex alpha:(CGFloat)alpha { | |
int red, green, blue; | |
blue = hex & 0x0000FF; | |
green = ((hex & 0x00FF00) >> 8); | |
red = ((hex & 0xFF0000) >> 16); | |
return [UIColor colorWithRed:red / 255.0f green:green / 255.0f blue:blue / 255.0f alpha:alpha]; | |
} | |
@end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment