重叠颜色的 alpha 值(
a2
)告诉你该颜色对总体的贡献百分比,而
(1 - a2)
告诉你原始颜色的贡献百分比。从这个角度来看,这是一个简单的计算:
func calculateColor(orgColor: UIColor, overlayColor: UIColor) -> UIColor {
func clampValue(_ v: CGFloat) -> CGFloat {
guard v > 0 else { return 0 }
guard v < 1 else { return 1 }
return v
}
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))
orgColor.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
overlayColor.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)
r1 = clampValue(r1)
g1 = clampValue(g1)
b1 = clampValue(b1)
r2 = clampValue(r2)
g2 = clampValue(g2)
b2 = clampValue(b2)
a2 = clampValue(a2)
let color = UIColor( red: r1 * (1 - a2) + r2 * a2,
green: g1 * (1 - a2) + g2 * a2,
blue: b1 * (1 - a2) + b2 * a2,
alpha: 1)
return color
}
直观上看,这是正确的。如果覆盖颜色完全不透明(
a2 == 1
),那么结果将是覆盖颜色。如果覆盖颜色完全透明(
a2 == 0
),则结果将是原始颜色。如果覆盖颜色的 alpha 值为
0.5
,则会得到两种颜色之间恰好中间的混合颜色。
在 Playground 中测试:
let c1 = UIColor(red: 27/255, green: 155/255, blue: 199/255, alpha: 1.0)
let c2 = UIColor(red: 188/255, green: 13/255, blue: 51/255, alpha: 0.37)
let c3 = calculateColor(orgColor: c1, overlayColor: c2)
let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
let view2 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view1.backgroundColor = c1
view2.backgroundColor = c2
view1.addSubview(view2)
let view3 = UIView(frame: CGRect(x: 100, y: 0, width: 100, height: 100))
view3.backgroundColor = c3
let view4 = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
view4.addSubview(view1)
view4.addSubview(view3)
view4
游乐场输出:
![Playground output](https://istack.dev59.com/uy1UM.webp)
0.0 ... 1.0
范围内,那么min
是不必要的,因为它们应该在这个范围内。即使r1
是1.0
,r2
是1.0
(它们的最大值),r1 *(1-a2)+ r2 * a2
的组合也将达到1.0
。尽管如此,仍然可以创建超出范围的UIColor
,即使它们被解释为被夹在该范围内,UIColor.getRed(green:blue:alpha:)
仍将返回超出范围的值。为了获得这些错误颜色的正确结果,有必要夹紧范围。请参见上面的修复。 - vacawama