2014-12-07 83 views
2

我有两个SKSpriteNode和他们的颜色是这样定义的:混合UIColors斯威夫特

colorNode[0].color = UIColor(red: 255, green: 0, blue: 0, alpha: 1) 
colorNode[1].color = UIColor(red: 0, green: 255, blue: 0, alpha: 1) 

,我想有两个第一批的混合着色第三SKSpriteNode,结果应该是这样的:

colorNode[2].color = UIColor(red: 255, green: 255, blue: 0, alpha: 1) 

但是有没有办法添加两个UIColors?就像这样:

colorNode[2].color = colorNode[0].color + colorNode[1].color 
+1

注意,颜色分量值'CGFloat's从'0.0'去'1.0',而不是从'0'到'255'。 – vacawama 2014-12-07 13:59:33

回答

3

怎么是这样的:

func addColor(_ color1: UIColor, with color2: 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)) 

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

    // add the components, but don't let them go above 1.0 
    return UIColor(red: min(r1 + r2, 1), green: min(g1 + g2, 1), blue: min(b1 + b2, 1), alpha: (a1 + a2)/2) 
} 

func multiplyColor(_ color: UIColor, by multiplier: CGFloat) -> UIColor { 
    var (r, g, b, a) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0)) 
    color.getRed(&r, green: &g, blue: &b, alpha: &a) 
    return UIColor(red: r * multiplier, green: g * multiplier, blue: b * multiplier, alpha: a) 
} 

定义运营商由Double添加颜色和乘颜色:

func +(color1: UIColor, color2: UIColor) -> UIColor { 
    return addColor(color1, with: color2) 
} 

func *(color: UIColor, multiplier: Double) -> UIColor { 
    return multiplyColor(color, by: CGFloat(multiplier)) 
} 

然后你可以混合颜色像这样:

// Make orange with 50% red and 50% yellow  
let orange = .red * 0.5 + .yellow * 0.5 

// Make light gray with 25% black and 75% white 
let lightGray = .black * 0.25 + .white * 0.75 

// Make sky blue by lightening a combination of 25% blue and 75% cyan 
let skyBlue = (.blue * 0.25 + .cyan * 0.75) * 0.25 + .white * 0.75 

// Make dark red by combining 50% red and 50% black 
let darkRed = .red * 0.50 + .black * 0.50 

// Make purple from 60% blue and 40% red 
let purple = (.blue * 0.60 + .red * 0.40) 

// Then make lavender from 25% purple and 75% white 
let lavender = purple * 0.25 + .white * 0.75 
+0

如何将其添加到扩展? – 2016-01-19 10:26:03

+1

max(r1,r2)不混合。如果您将黑色与白色混合,则使用此解决方案时,它会变成白色。 – 2017-02-07 14:01:09

+0

@RobertGummesson,你是对的。我回应刚加入组件的OP。我已经用可用于混合颜色的解决方案更新了答案。 – vacawama 2017-07-19 02:02:26

3

Swift3版本,扩展了一些更多的警卫和细粒度的调整:

extension UIColor { 
    static func blend(color1: UIColor, intensity1: CGFloat = 0.5, color2: UIColor, intensity2: CGFloat = 0.5) -> UIColor { 
     let total = intensity1 + intensity2 
     let l1 = intensity1/total 
     let l2 = intensity2/total 
     guard l1 > 0 else { return color2} 
     guard l2 > 0 else { return color1} 
     var (r1, g1, b1, a1): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0) 
     var (r2, g2, b2, a2): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0) 

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

     return UIColor(red: l1*r1 + l2*r2, green: l1*g1 + l2*g2, blue: l1*b1 + l2*b2, alpha: l1*a1 + l2*a2) 
    } 
} 
+0

唯一的问题是,如果你使用它和扩展名,你实际上并不需要color1参数。你可以用self来代替。 – Andreas777 2017-06-13 13:36:01

+0

对不起,我没有注意到是静态的... – Andreas777 2017-06-13 13:38:56

+0

@ Andreas777如果你想你可以修改它是一个实例函数,但我喜欢与(color1,intensity1,color2,intensity2)的对称 – Bersaelor 2017-06-13 21:11:47

1

我的版本(它融合尽可能多的颜色,只要你愿意),斯威夫特4+

func blend(colors: [UIColor]) -> UIColor { 
    let numberOfColors = CGFloat(colors.count) 
    var (red, green, blue, alpha) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0)) 

    let componentsSum = colors.reduce((red: CGFloat(0), green: CGFloat(0), blue: CGFloat(0), alpha: CGFloat())) { temp, color in 
     color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) 
     return (temp.red+red, temp.green + green, temp.blue + blue, temp.alpha+alpha) 
    } 
    return UIColor(red: componentsSum.red/numberOfColors, 
         green: componentsSum.green/numberOfColors, 
         blue: componentsSum.blue/numberOfColors, 
         alpha: componentsSum.alpha/numberOfColors) 
} 
+0

如果您的颜色不是来自RGB颜色空间的颜色,例如UIColor.lightGray,则会失败。如果您想要混合使用,您需要使用UIColor.getRed(_:green:blue:alpha :)提取组件。 UIColor.white与UIColor.blue – Noyer282 2018-02-28 00:05:49

+0

嗨Noyer282,请你用你的建议编辑/更新我的答案?谢谢:) – 2018-02-28 03:08:14

+0

没有。您可以通过尝试let blended = blend(颜色:[UIColor.white,UIColor.red])。你原来的代码会崩溃,但现在它应该可以工作。 – Noyer282 2018-02-28 12:33:55

0

对于我的项目,我需要在白色背景下模拟一个动态的主题颜色,并且没有任何实际的透明度。我可以用下面的UIColor扩展(基于this answer)来实现这一目标:

static func simulatingAlpha(_ alpha: CGFloat, for color1: UIColor, over color2: UIColor) -> UIColor { 

    let whiteComponents: [CGFloat] = [1.0, 1.0, 1.0, 1.0] //UIColor.white.cgColor.components only returns [1.0, 1.0] 

    var rgba1: [CGFloat] = whiteComponents //set a valid default 
    var rgba2: [CGFloat] = whiteComponents 

    if let components = color1.cgColor.components, components.count > 2 { 
     rgba1 = components 
    } 

    if let components = color2.cgColor.components, components.count > 2 { 
     rgba2 = components 
    } 

    let r1: CGFloat = rgba1[0] 
    let g1: CGFloat = rgba1[1] 
    let b1: CGFloat = rgba1[2] 

    let r2: CGFloat = rgba2[0] 
    let g2: CGFloat = rgba2[1] 
    let b2: CGFloat = rgba2[2] 

    let r3 = ((1 - alpha) * r2) + (r1 * alpha) 
    let g3 = ((1 - alpha) * g2) + (g1 * alpha) 
    let b3 = ((1 - alpha) * b2) + (b1 * alpha) 

    print("Simulated RGB: \(Int(r3 * 255)), \(Int(g3 * 255)), \(Int(b3 * 255))") 

    let newComponents: [CGFloat] = [r3, g3, b3, 1.0] 
    let space = CGColorSpace(name:CGColorSpace.sRGB)! 
    guard let cgColor3 = CGColor(colorSpace: space, components: newComponents) else { 
     print("Failed to create new CGColor in default color space") 
     return color1 
    } 

    return UIColor(cgColor: cgColor3) 
} 
0

的代码已经实现了所有的you.Don't忘记给我一个开始图层混合的photoshop.If是有用。玩得开心〜

GitHub上:https://github.com/Orange-W/PhotoshopBending

import Foundation 
import UIKit 

extension UIColor { 
    // MARK: - 常用叠图 
    // Alpha Blending 前景色叠图 
    func blendAlpha(coverColor: UIColor) -> UIColor { 
     let c1 = coverColor.rgbaTuple() 
     let c2 = self.rgbaTuple() 

     let c1r = CGFloat(c1.r) 
     let c1g = CGFloat(c1.g) 
     let c1b = CGFloat(c1.b) 

     let c2r = CGFloat(c2.r) 
     let c2g = CGFloat(c2.g) 
     let c2b = CGFloat(c2.b) 

     // 前景色叠图公式 
     let r = c1r * c1.a + c2r * (1 - c1.a) 
     let g = c1g * c1.a + c2g * (1 - c1.a) 
     let b = c1b * c1.a + c2b * (1 - c1.a) 

     return UIColor.init(red: r/255.0, green: g/255.0, blue: b/255.0, alpha: 1.0) 
    } 


    // MARK: - 去亮度型 
    /// Darken 变暗 B<=A: C=B; B>=A: C=A 
    func blendDarken(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { return ($0 <= $1) ? $0 : $1 } 
    } 

    /// Multiply 正片叠底 C = A*B 
    func blendMultiply(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { return $0 * $1 } 
    } 

    /// Color Burn 颜色加深 C=1-(1-B)/A 
    func blendColorBurn(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { return 1 - (1 - $0)/$1 } 
    } 

    /// Linear Burn 线性加深 C=A+B-1 
    func blendLinearBurn(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { return ($1 + $0) - 1.0 } 
    } 

    // MARK: - 去暗型 
    /// Lighten 变亮 B>=A: C=B; B<=A: C=A 
    func blendLighten(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { return ($0 >= $1) ? $0 : $1 } 
    } 

    /// Screen 滤色 C=1-(1-A)*(1-B), 也可以写成 1-C=(1-A)*(1-B) 
    func blendScreen(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { return 1 - (1 - $1) * (1 - $0) } 
    } 

    /// Color Dodge 颜色减淡 C=B/(1-A) 
    func blendColorDodge(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { 
      if $1 >= 1.0 { return $1 } 
      else { return min(1.0, $0/(1 - $1)) } 
     } 
    } 

    /// Linear Dodge 线性减淡 C=A+B 
    func blendLinearDodge(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { return min(1, $1 + $0) } 
    } 


    // MARK: - 溶合型 
    /// Overlay 叠加 B<=0.5: C=2*A*B; B>0.5: C=1-2*(1-A)*(1-B) 
    func blendOverlay(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { 
      if $0 <= 0.5 { return 2 * $1 * $0 } 
      else { return 1 - 2 * (1 - $1) * (1 - $0) } 
     } 
    } 

    /// Soft Light 柔光 A<=0.5: C=(2*A-1)*(B-B*B)+B; A>0.5: C=(2*A-1)*(sqrt(B)-B)+B 
    func blendSoftLight(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { 
      if $1 <= 0.5 { return (2 * $1 - 1) * ($0 - $0 * $0) + $0 } 
      else { return (2 * $1 - 1)*(sqrt($0) - $0) + $0 } 
     } 
    } 

    /// Hard Light 强光 A<=0.5: C=2*A*B; A>0.5: C=1-2*(1-A)*(1-B) 
    func blendHardLight(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { 
      if $1 <= 0.5 { return 2 * $1 * $0 } 
      else { return 1 - 2 * (1 - $1) * (1 - $0) } 
     } 
    } 

    /// Vivid Light 亮光 A<=0.5: C=1-(1-B)/(2*A); A>0.5: C=B/(2*(1-A)) 
    func blendVividLight(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { 
      if $1 <= 0.5 { return self.fitIn((1 - (1 - $0)/(2 * $1)), ceil: 1.0) } 
      else { return self.fitIn($0/(2 * (1 - $1)), ceil: 1.0) } 
     } 
    } 

    /// Linear Light 线性光 C=B+2*A-1 
    func blendLinearLight(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { return self.fitIn($0 + 2 * $1 - 1, ceil: 1.0) } 
    } 

    /// Pin Light 点光 
    /// B<2*A-1:  C=2*A-1 
    /// 2*A-1<B<2*A: C=B 
    /// B>2*A:  C=2*A 
    func blendPinLight(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { 
      if $0 <= 2 * $1 - 1 { return 2 * $1 - 1 } 
      else if (2 * $1 - 1 < $0) && ($0 < 2 * $1) { return $0} 
      else { return 2 * $1 } 
     } 
    } 

    /// Hard Mix 实色混合A<1-B: C=0; A>1-B: C=1 
    func blendHardMix(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { 
      if $1 <= 1 - $0 { return 0 } 
      else { return 1 } 
     } 
    } 

    // MARK: - 色差型 
    /// Difference 差值 C=|A-B| 
    func blendDifference(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { fabs($1 - $0) } 
    } 

    /// Exclusion 排除 C = A+B-2*A*B 
    func blendExclusion(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { $1 + $0 - 2 * $1 * $0 } 
    } 

    /// 减去 C=A-B 
    func blendMinus(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { $1 - $0 } 
    } 

    /// 划分 C=A/B 
    func blendDivision(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor { 
     return blendProcedure(coverColor: coverColor, alpha: alpha) { 
      if $0 == 0{ 
       return 1.0 
      }else { 
       return self.fitIn($1/$0, ceil: 1.0) 
      } 
     } 
    } 

    // MARK: 处理函数 
    func blendProcedure(
     coverColor: UIColor, 
     alpha: CGFloat, 
     procedureBlock: ((_ baseValue: CGFloat,_ topValue: CGFloat) -> CGFloat)? 
     ) -> UIColor { 
     let baseCompoment = self.rgbaTuple() 
     let topCompoment = coverColor.rgbaTuple() 

     // 该层透明度 
     let mixAlpha = alpha * topCompoment.a + (1.0 - alpha) * baseCompoment.a 

     // RGB 值 
     let mixR = procedureBlock?(
      baseCompoment.r/255.0, 
      topCompoment.r/255.0) 
      ?? (baseCompoment.r)/255.0 

     let mixG = procedureBlock?(
      baseCompoment.g/255.0, 
      topCompoment.g/255.0) 
      ?? (baseCompoment.g)/255.0 

     let mixB = procedureBlock?(
      baseCompoment.b/255.0, 
      topCompoment.b/255.0) 
      ?? baseCompoment.b/255.0 


     return UIColor.init(red: fitIn(mixR), 
          green: fitIn(mixG), 
          blue: fitIn(mixB), 
          alpha: mixAlpha) 
    } 

    // 防止越界 
    func fitIn(_ value: CGFloat, ceil: CGFloat = 255) -> CGFloat { return max(min(value,ceil),0) } 
    func fitIn(_ value: Double, ceil: CGFloat = 255) -> CGFloat { return fitIn(CGFloat(value), ceil: ceil) } 

    // 返回 RBGA 
    func rgbaTuple() -> (r: CGFloat, g: CGFloat, b: CGFloat,a: CGFloat) { 
     var r: CGFloat = 0 
     var g: CGFloat = 0 
     var b: CGFloat = 0 
     var a: CGFloat = 0 
     self.getRed(&r, green: &g, blue: &b, alpha: &a) 
     r = r * 255 
     g = g * 255 
     b = b * 255 

     return ((r),(g),(b),a) 
    } 
}