2014-12-07 3 views
2

Я два SKSpriteNode и их цвета определяются следующим образом:Смешать UIColors в Swift

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

ответ

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) 
} 

Define операторы, чтобы добавить цвета и умножить цвет на 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

Как вы можете добавить это расширение? –

+1

max (r1, r2) не смешивается. Если вы смешаете черный с белым, он просто закончит белым с этим решением. –

+0

@RobertGummesson, ты прав. Я отвечал на ОП, который просто добавлял компоненты. Я обновил ответ с помощью решения, которое можно использовать для смешивания цветов. – vacawama

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, если вы делаете это и расширение. Вместо этого вы можете использовать «я». – Andreas777

+0

Извините, я не заметил, является статическим ... – Andreas777

+0

@ Andreas777, если вы хотите, вы можете изменить его как функцию экземпляра, но мне понравилась симметрия с (color1, intensity1, color2, intensity2) – Bersaelor

1

Моя версия (она сочетает в себе столько цветов, как вы хотите), Swift 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

+0

Привет, Noyer282, не могли бы вы отредактировать/обновить свой ответ с вашего предложения? Спасибо :) –

+0

Сделал это. Вы можете проверить это, попробовав, например. let blended = blend (цвета: [UIColor.white, UIColor.red]). Исправлен исходный код, но теперь он должен работать. – Noyer282

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

код достиг всего слой смесь для photoshop.If полезна для you.Don't забудьте дать мне старт , Весело ~

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) 
    } 
}