如何在iOS中获取两个UIColor之间的中间颜色

11

如果我提供两种颜色

UIColor *color1 = [UIColor blackColor];
UIColor *color2 = [UIColor whiteColor];

我应该得到灰色(grayColor)作为结果,我该如何实现?


另一个例子是:如果我给出红色和黄色,我应该得到橙色。 - Sunil Rao
获取红色、蓝色、绿色分量的数值平均值。 - El Tomato
方法应该是相同的。只需使用 getRed:green:blue:alpha: 获取红/蓝/绿的值,或者也许需要使用 getHue:saturation:brightness:alpha: 进行一些处理。 - Larme
5
重复问题:http://stackoverflow.com/questions/23358123/get-midcolor-from-uicolor从UIColor获取中间颜色。 - enzo
3个回答

13

找到“中间值”的简单方法是对四个组成部分取平均值,如下所示:

UIColor *color1 = [UIColor blackColor];
UIColor *color2 = [UIColor whiteColor];
CGFloat r1, r2, g1, g2, b1, b2, a1, a2;
[color1 getRed:&r1 green:&g1 blue:&b1 alpha:&a1];
[color2 getRed:&r2 green:&g2 blue:&b2 alpha:&a2];
UIColor *avg = [UIColor colorWithRed:(r1+r2)/2.0f
                              green:(g1+g2)/2.0f
                               blue:(b1+b2)/2.0f
                              alpha:(a1+a2)/2.0f];

请注意,此方法生成的是一种中间点RGBA颜色空间,而这只是众多可能颜色空间中的一种。在其他颜色空间中对分量进行平均将导致不同的结果。


UIColor类参考。可能会有用。 - Arc676
这个程序是否总是能得到预期的结果?是否有可能混合两种颜色,但却得到了泥泞的颜色而不是预期的颜色? - Fogmeister
1
@Fogmeister 我非常确定这 不会 总是符合期望,因为人们不会从 RGBA 颜色空间的角度考虑颜色。由于颜色敏感性高度个体化,几乎不可能想出一种满足所有人的方法。 - Sergey Kalinichenko
@dasblinkenlight 我想在这两种颜色之间有多个阴影。我该怎么做?有什么想法吗? - Arpan Dixit

4

使用Swift 4+进行回答

func blend(colors: [UIColor]) -> UIColor {
    let componentsSum = colors.reduce((red: CGFloat(0), green: CGFloat(0), blue: CGFloat(0))) { (temp, color) in
      guard let components = color.cgColor.components else { return temp }
      return (temp.0 + components[0], temp.1 + components[1], temp.2 + components[2])
    }
    let components = (red: componentsSum.red / CGFloat(colors.count) ,
                      green: componentsSum.green / CGFloat(colors.count),
                      blue: componentsSum.blue / CGFloat(colors.count))
    return UIColor(red: components.red, green: components.green, blue: components.blue, alpha: 1)
  }

它可以混合任意数量的颜色。

你的代码在颜色数组中带白色元素时不起作用。我已经提出了一个编辑来修复这个问题。 - Maschina

1

这里是Swift实现的代码,可以安全地使用。它适用于不同颜色空间的颜色,但会混合RGBA颜色:

func + (left: UIColor, right: UIColor) -> UIColor {
    var (r1, g1, b1, a1) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))
    var (r2, g2, b2, a2) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))
    left.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
    right.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)
    return UIColor(red: (r1 + r2)/2, green: (g1 + g2)/2, blue: (b1 + b2)/2, alpha: (a1 + a2)/2)
}

使用中:
    view.backgroundColor = .red + .white

旧答案:

extension UIColor {

    func blended(with color: UIColor) -> UIColor? {
        guard cgColor.colorSpace == color.cgColor.colorSpace else { return nil }
        return UIColor(cgColor: CGColor(colorSpace: cgColor.colorSpace!, components:
            zip(cgColor.components!, color.cgColor.components!).map { ($0 + $1) / 2 }
        )!)
    }
}

但它只能使用一个颜色空间的颜色,否则它将返回nil。 这是使用示例:
let white = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
view.backgroundColor = UIColor.red.blended(with: white)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接