可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a ProgressBar to which I want to assign a customColor color and based on the progress fade to another color. Using the method below I get a dark rainbow effect color including reds and dark brown and dark green. The start color will be a light blue one and the destination color a light green.
-(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;
}
回答1:
You can do a "linear interpolation" between the colors:
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];
This gives the initial color for progress == 0
and the final color for
progress == 1
.
回答2:
Swift version converted from the code from 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)
回答3:
Here is a category for UIColor
that can be used to linearly interpolate between two UIColor
s in either RGB or HSV:
@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
回答4:
The swift version provided above doesn't work with the white color, here the solution:
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)
回答5:
Another port to swift, as an extension to UIColor. This time both interpolation functions.
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)
}
}
回答6:
Here's a Swift 3 version that uses a convenience initializer and adds a function to return an array of intermediate colors.
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
}
}
Usage:
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)
Output:
[
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
]