基于进度值的UIColor转换

我有一个ProgressBar我要分配一个customColor颜色,并基于进展淡入到另一种颜色。 使用下面的方法,我得到一个黑暗的彩虹效果颜色,包括红色,深褐色和深绿色。 起始颜色将是浅蓝色,目标颜色是浅绿色。

-(UIColor *) makeCustomColorFromProgressValue:(float) progress{ UIColor *color; // startColor Color - lightBlue float red = 0.53; float green = 0.82; float blue = 1; //Destination Color - lightGreen float finalRed = 0.53; float finalGreen = 1; float finalBlue = 0.82; float newRed = 80;//finalRed *255; float newGreen = (finalGreen *progress) *255; float newBlue = (finalBlue *progress) *255; color = Rgb2UIColor(newRed, newGreen, newBlue); return color; } 

你可以在颜色之间做一个“线性插值”:

 CGFloat newRed = (1.0 - progress) * red + progress * finalRed; CGFloat newGreen = (1.0 - progress) * green + progress * finalGreen; CGFloat newBlue = (1.0 - progress) * blue + progress * finalBlue; UIColor *color = [UIColor colorWithRed:newRed green:newGreen blue:newBlue alpha:1.0]; 

这给出progress == 0的最初颜色和progress == 1的最终颜色。

Swift版本由Jonathan Ellis的代码转换而来

 extension UIColor { func interpolateRGBColorTo(_ end: UIColor, fraction: CGFloat) -> UIColor? { let f = min(max(0, fraction), 1) guard let c1 = self.cgColor.components, let c2 = end.cgColor.components else { return nil } let r: CGFloat = CGFloat(c1[0] + (c2[0] - c1[0]) * f) let g: CGFloat = CGFloat(c1[1] + (c2[1] - c1[1]) * f) let b: CGFloat = CGFloat(c1[2] + (c2[2] - c1[2]) * f) let a: CGFloat = CGFloat(c1[3] + (c2[3] - c1[3]) * f) return UIColor(red: r, green: g, blue: b, alpha: a) } } let color1 = UIColor(red: 0.035, green: 0.216, blue: 0.933, alpha: 1.00) let color2 = UIColor(red: 0.933, green: 0.794, blue: 0.000, alpha: 1.00) color1.interpolateRGBColorTo(color2, fraction:0.1) 

UIColor插值

这里是UIColor一个类别,它可以用于在RGB或HSV中的两个UIColor之间进行线性插值:

 @implementation UIColor (Interpolate) + (UIColor *)interpolateRGBColorFrom:(UIColor *)start to:(UIColor *)end withFraction:(float)f { f = MAX(0, f); f = MIN(1, f); const CGFloat *c1 = CGColorGetComponents(start.CGColor); const CGFloat *c2 = CGColorGetComponents(end.CGColor); CGFloat r = c1[0] + (c2[0] - c1[0]) * f; CGFloat g = c1[1] + (c2[1] - c1[1]) * f; CGFloat b = c1[2] + (c2[2] - c1[2]) * f; CGFloat a = c1[3] + (c2[3] - c1[3]) * f; return [UIColor colorWithRed:r green:g blue:b alpha:a]; } + (UIColor *)interpolateHSVColorFrom:(UIColor *)start to:(UIColor *)end withFraction:(float)f { f = MAX(0, f); f = MIN(1, f); CGFloat h1,s1,v1,a1; [start getHue:&h1 saturation:&s1 brightness:&v1 alpha:&a1]; CGFloat h2,s2,v2,a2; [end getHue:&h2 saturation:&s2 brightness:&v2 alpha:&a2]; CGFloat h = h1 + (h2 - h1) * f; CGFloat s = s1 + (s2 - s1) * f; CGFloat v = v1 + (v2 - v1) * f; CGFloat a = a1 + (a2 - a1) * f; return [UIColor colorWithHue:h saturation:s brightness:v alpha:a]; } @end 

上面提供的swift版本不能用白色工作,这里的解决办法是:

 struct ColorComponents { var r:CGFloat, g:CGFloat, b:CGFloat, a:CGFloat } extension UIColor { func getComponents() -> ColorComponents { if (cgColor.numberOfComponents == 2) { let cc = cgColor.components! return ColorComponents(r:cc[0], g:cc[0], b:cc[0], a:cc[1]) } else { let cc = cgColor.components! return ColorComponents(r:cc[0], g:cc[1], b:cc[2], a:cc[3]) } } func interpolateRGBColorTo(end: UIColor, fraction: CGFloat) -> UIColor { var f = max(0, fraction) f = min(1, fraction) let c1 = self.getComponents() let c2 = end.getComponents() let r = c1.r + (c2.r - c1.r) * f let g = c1.g + (c2.g - c1.g) * f let b = c1.b + (c2.b - c1.b) * f let a = c1.a + (c2.a - c1.a) * f return UIColor.init(red: r, green: g, blue: b, alpha: a) } } let color1 = UIColor.whiteColor() let color2 = UIColor(red: 0.933, green: 0.794, blue: 0.000, alpha: 1.00) color1.interpolateRGBColorTo(color2, fraction:0.1) color1.interpolateRGBColorTo(color2, fraction:0.2) color1.interpolateRGBColorTo(color2, fraction:0.3) 

❤︎游乐场

另一个端口很快,作为UIColor的扩展。 这次是插值function。

 extension UIColor { func interpolateRGBColorTo(end:UIColor, fraction:CGFloat) -> UIColor { var f = max(0, fraction) f = min(1, fraction) let c1 = CGColorGetComponents(self.CGColor) let c2 = CGColorGetComponents(end.CGColor) let r: CGFloat = CGFloat(c1[0] + (c2[0] - c1[0]) * f) let g: CGFloat = CGFloat(c1[1] + (c2[1] - c1[1]) * f) let b: CGFloat = CGFloat(c1[2] + (c2[2] - c1[2]) * f) let a: CGFloat = CGFloat(c1[3] + (c2[3] - c1[3]) * f) return UIColor.init(red:r, green:g, blue:b, alpha:a) } func interpolateHSVColorFrom(end: UIColor, fraction: CGFloat) -> UIColor { var f = max(0, fraction) f = min(1, fraction) var h1: CGFloat = 0, s1: CGFloat = 0, b1: CGFloat = 0, a1: CGFloat = 0 self.getHue(&h1, saturation: &s1, brightness: &b1, alpha: &a1) var h2: CGFloat = 0, s2: CGFloat = 0, b2: CGFloat = 0, a2: CGFloat = 0 end.getHue(&h2, saturation: &s2, brightness: &b2, alpha: &a2) let h = h1 + (h2 - h1) * f let s = s1 + (s2 - b1) * f let b = b1 + (b2 - b1) * f let a = a1 + (a2 - a1) * f return UIColor(hue: h, saturation: s, brightness: b, alpha: a) } } 

这里有一个Swift 3版本,它使用了一个方便的初始化器,并添加了一个函数来返回一个中间色的数组。

 extension UIColor { convenience init?(interpolatedFrom fromColor: UIColor, to toColor: UIColor, byFraction fraction: CGFloat) { guard fromColor.cgColor.numberOfComponents >= 4 && toColor.cgColor.numberOfComponents >= 3 else { print("Color interpolation requires both the to and from color to be provided with components for red, green, blue, and alpha.") return nil } var fraction = max(0, fraction) fraction = min(1, fraction) guard let fromComponents = fromColor.cgColor.components, let toComponents = toColor.cgColor.components else { print("Unable to extract components from colors provided for interpolation.") return nil } let red: CGFloat = CGFloat(fromComponents[0] + (toComponents[0] - fromComponents[0]) * fraction) let green: CGFloat = CGFloat(fromComponents[1] + (toComponents[1] - fromComponents[1]) * fraction) let blue: CGFloat = CGFloat(fromComponents[2] + (toComponents[2] - fromComponents[2]) * fraction) let alpha: CGFloat = CGFloat(fromComponents[3] + (toComponents[3] - fromComponents[3]) * fraction) self.init(red:red, green:green, blue:blue, alpha:alpha) } class func interpolateColors(from fromColor: UIColor, to toColor: UIColor, interpolations: Int) -> [UIColor] { guard interpolations > 2 else { return [fromColor, toColor] } let increment = CGFloat(1) / CGFloat(interpolations - 1) var result = [UIColor]() for i in 0..<interpolations { let fraction = CGFloat(i) * increment guard let color = UIColor(interpolatedFrom: fromColor, to: toColor, byFraction: fraction) else { print("Unable to create an interpolated color for fraction \(fraction). Will use gray instead.") result.append(.gray) continue } result.append(color) } return result } } 

用法:

 let color1 = UIColor(red: 0.137, green: 0.157, blue: 0.196, alpha: 1) let color2 = UIColor(red: 0.455, green: 0.475, blue: 0.525, alpha: 1) let interpolatedColors = UIColor.interpolateColors(from: color1, to: color2, interpolations: 5) 

输出:

 [ r 0.137 g 0.157 b 0.196 a 1.0, r 0.216 g 0.236 b 0.278 a 1.0, r 0.296 g 0.316 b 0.361 a 1.0, r 0.375 g 0.396 b 0.443 a 1.0, r 0.455 g 0.475 b 0.525 a 1.0 ]