Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Swift中,通过将颜色与透明颜色叠加而获得的无透明度颜色_Swift_Colors - Fatal编程技术网

在Swift中,通过将颜色与透明颜色叠加而获得的无透明度颜色

在Swift中,通过将颜色与透明颜色叠加而获得的无透明度颜色,swift,colors,Swift,Colors,我有一个原始UIView,它具有非透明的颜色orgColor 这由一个覆盖UIView覆盖,该视图具有一个带有透明度(alpha通道)的OverlyColor 给定这两种颜色orgColor和overlycolor我如何计算calculatedColor,它应该没有任何透明度,但在屏幕上是完全相同的颜色,就好像两个视图实际上会被覆盖一样 我已经为此编写了一个框架函数(以显示原理)。但不知道如何计算(我在堆栈溢出上发现了一些关于颜色混合的帖子,但没有一篇会真正去除结果中的透明度…) 叠加颜色的a

  • 我有一个原始UIView,它具有非透明的颜色
    orgColor
  • 这由一个覆盖UIView覆盖,该视图具有一个带有透明度(alpha通道)的
    OverlyColor
给定这两种颜色
orgColor
overlycolor
我如何计算
calculatedColor
,它应该没有任何透明度,但在屏幕上是完全相同的颜色,就好像两个视图实际上会被覆盖一样

我已经为此编写了一个框架函数(以显示原理)。但不知道如何计算(我在堆栈溢出上发现了一些关于颜色混合的帖子,但没有一篇会真正去除结果中的透明度…)


叠加颜色的alpha(
a2
)告诉您颜色占总颜色的百分比,
(1-a2)
告诉您原始颜色占总颜色的百分比。因此,这是一个简单的计算:

func calculateColor(orgColor: UIColor, overlayColor: UIColor) -> UIColor {
    // Helper function to clamp values to range (0.0 ... 1.0)
    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)

    // Make sure the input colors are well behaved
    // Components should be in the range (0.0 ... 1.0)
    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
}
操场输出:

// Make these colors anything you want
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

// Overlay view2 onto view1
view1.addSubview(view2)

// view3 has the calculated color
let view3 = UIView(frame: CGRect(x: 100, y: 0, width: 100, height: 100))
view3.backgroundColor = c3

// display the views side by side in view4
let view4 = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
view4.addSubview(view1)
view4.addSubview(view3)

// display this view and see that the two halves match
view4

根据@vacawama的回答(全归功于他!),我为UIColor写了以下扩展:

extension UIColor {

    func solidColorWhenOverlayed(by overlayColor: UIColor) -> UIColor {
        // Helper function to clamp values to range (0.0 ... 1.0)
        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))

        getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
        overlayColor.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)

        // Make sure the input colors are well behaved
        // Components should be in the range (0.0 ... 1.0)
        // This to compensate for any "bad" colors = colors which have component values out of range
        r1 = clampValue(r1)
        g1 = clampValue(g1)
        b1 = clampValue(b1)

        r2 = clampValue(r2)
        g2 = clampValue(g2)
        b2 = clampValue(b2)
        a2 = clampValue(a2)

        return UIColor(  red  : r1 * (1 - a2) + r2 * a2,
                         green: g1 * (1 - a2) + g2 * a2,
                         blue : b1 * (1 - a2) + b2 * a2,
                         alpha: 1)
    }

}
扩展UIColor{ func solidColorWhenOverlayed(通过叠加颜色:UIColor)->UIColor{ //用于将值钳制到范围(0.0…1.0)的辅助函数 func clampValue(v:CGFloat)->CGFloat{ 保护v>0其他{返回0} 保护v<1 else{return 1} 返回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)) 红色(&r1,绿色:&g1,蓝色:&b1,阿尔法:&a1) 套色。红色(&r2,绿色:&g2,蓝色:&b2,阿尔法:&a2) //确保输入颜色表现良好 //组件应在(0.0…1.0)范围内 //这是为了补偿任何“坏”颜色=组件值超出范围的颜色 r1=clampValue(r1) g1=clampValue(g1) b1=夹具值(b1) r2=clampValue(r2) g2=clampValue(g2) b2=clampValue(b2) a2=夹持值(a2) 返回UIColor(红色:r1*(1-a2)+r2*a2, 绿色:g1*(1-a2)+g2*a2, 蓝色:b1*(1-a2)+b2*a2, 阿尔法:1) } }
vacawama这台机器非常好用!非常好的格式和完整的答案以及。只需一句话:在颜色计算中,我们是否应该使用min(…,1.0)函数输入值不能大于1.0(在其他混合计算的答案中发现了这一点)?检查我编写的扩展名(全部归功于您!),如果输入值在
0.0范围内,则不需要
min
。。。1.0
按原样。即使
r1
1.0
r2
1.0
(其最大值),
r1*(1-a2)+r2*a2
的组合将在
1.0
时达到最大值。也就是说,可以使用超出范围的值创建
UIColor
s,即使它们被解释为钳制在该范围内,
UIColor.getRed(绿色:蓝色:alpha:)
仍将返回超出范围的值。为了获得这些不良颜色的正确结果,有必要钳制范围。查看上面的修复。样式问题:我建议使用
self.getRed
而不是
getRed
,因为它更清楚地显示了正在发生的事情。见我上面提到的夹具问题。你的
min
解决方案不会帮助输入不好的颜色。我喜欢扩展。您可能希望将其命名为
solidColorWhenOverlayed(通过overlycolor:UIColor)
,这与Swift 3/4的冗余较少的样式更为一致。
extension UIColor {

    func solidColorWhenOverlayed(by overlayColor: UIColor) -> UIColor {
        // Helper function to clamp values to range (0.0 ... 1.0)
        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))

        getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
        overlayColor.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)

        // Make sure the input colors are well behaved
        // Components should be in the range (0.0 ... 1.0)
        // This to compensate for any "bad" colors = colors which have component values out of range
        r1 = clampValue(r1)
        g1 = clampValue(g1)
        b1 = clampValue(b1)

        r2 = clampValue(r2)
        g2 = clampValue(g2)
        b2 = clampValue(b2)
        a2 = clampValue(a2)

        return UIColor(  red  : r1 * (1 - a2) + r2 * a2,
                         green: g1 * (1 - a2) + g2 * a2,
                         blue : b1 * (1 - a2) + b2 * a2,
                         alpha: 1)
    }

}