80 votes

Obtenez des variations de couleurs plus claires et plus foncées pour une UIColor donnée.

Comment obtenir des variations plus claires et plus foncées d'une UIColor donnée en Swift ?

enter image description here

1 votes

La question du titre est assez triviale et permet différentes solutions ; vous pouvez également utiliser une fonction au lieu de deux en utilisant un paramètre d'entrée négatif.

0 votes

Différentes techniques ont été proposées ici stackoverflow.com/questions/11598043/ il y a aussi des réponses en Swift.

0 votes

@ShadowOf mis à jour, merci pour la contribution.

168voto

Steve Points 966

Mise à jour de

Utilisez ci-dessous UIColor Extension :

extension UIColor {

    func lighter(by percentage: CGFloat = 30.0) -> UIColor? {
        return self.adjust(by: abs(percentage) )
    }

    func darker(by percentage: CGFloat = 30.0) -> UIColor? {
        return self.adjust(by: -1 * abs(percentage) )
    }

    func adjust(by percentage: CGFloat = 30.0) -> UIColor? {
        var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
        if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) {
            return UIColor(red: min(red + percentage/100, 1.0),
                           green: min(green + percentage/100, 1.0),
                           blue: min(blue + percentage/100, 1.0),
                           alpha: alpha)
        } else {
            return nil
        }
    }
}

Utilisation :

let color = UIColor(red:0.96, green:0.54, blue:0.10, alpha:1.0)
color.lighter(30) // returns lighter color by 30%
color.darker(30) // returns darker color by 30%

au lieu de .lighter() et .darker() vous pouvez utiliser .adjust() avec des valeurs positives pour l'éclaircissement et des valeurs négatives pour l'assombrissement.

color.adjust(-30) // 30% darker color
color.adjust(30) // 30% lighter color

Sortie :

enter image description here

3 votes

Vous modifiez tous les composants par la même valeur au lieu de les changer proportionnellement. Voyez comment l'orange devient jaune lorsque vous l'éclaircissez.

0 votes

L'addition des valeurs proportionnellement n'est pas correcte. Essayez cette couleur UIColor(red:0.89, green:0.28, blue:0.00, alpha:1.0)

4 votes

Mais ajouter la même valeur à tous les composants n'est pas correct non plus, cela change la couleur. Jetez un coup d'œil aux différentes réponses à stackoverflow.com/questions/11598043/ où le luminosité dans la représentation HSB est ajustée.

56voto

Tran Quan Points 483

Je veux fournir une autre version utilisant la luminosité et la saturation au lieu du RGB.

extension UIColor {
  /**
   Create a ligher color
   */
  func lighter(by percentage: CGFloat = 30.0) -> UIColor {
    return self.adjustBrightness(by: abs(percentage))
  }

  /**
   Create a darker color
   */
  func darker(by percentage: CGFloat = 30.0) -> UIColor {
    return self.adjustBrightness(by: -abs(percentage))
  }

  /**
   Try to increase brightness or decrease saturation
   */
  func adjustBrightness(by percentage: CGFloat = 30.0) -> UIColor {
    var h: CGFloat = 0, s: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
    if self.getHue(&h, saturation: &s, brightness: &b, alpha: &a) {
      if b < 1.0 {
        let newB: CGFloat = max(min(b + (percentage/100.0)*b, 1.0), 0.0)
        return UIColor(hue: h, saturation: s, brightness: newB, alpha: a)
      } else {
        let newS: CGFloat = min(max(s - (percentage/100.0)*s, 0.0), 1.0)
        return UIColor(hue: h, saturation: newS, brightness: b, alpha: a)
      }
    }
    return self
  }
}

8 votes

Je pense que c'est mieux que de modifier les valeurs RVB

0 votes

Je ne pense pas que cela fonctionne lorsque la saturation est à 0 et la luminosité à 1.0. IE blanc. Dans ce cas, vous vous retrouvez avec une saturation inchangée.

1 votes

(Vous ne pouvez pas éclaircir le blanc.) C'est l'approche correcte. Les réponses RVB sont totalement incorrectes à bien des égards.

3voto

lukszar Points 114

Version avec modification des valeurs RVB

Ici, j'ai mis simple UIColor qui est basé sur les réponses précédentes. Elle fonctionne parfaitement pour moi.

Démonstration ci-dessous :

Colors demo

Code de manipulation des couleurs

public extension UIColor {

    /**
     Create a lighter color
     */
    public func lighter(by percentage: CGFloat = 30.0) -> UIColor {
        return self.adjustBrightness(by: abs(percentage))
    }

    /**
     Create a darker color
     */
    public func darker(by percentage: CGFloat = 30.0) -> UIColor {
        return self.adjustBrightness(by: -abs(percentage))
    }

    /**
     Changing R, G, B values
     */

    func adjustBrightness(by percentage: CGFloat = 30.0) -> UIColor {

        var red: CGFloat = 0.0
        var green: CGFloat = 0.0
        var blue: CGFloat = 0.0
        var alpha: CGFloat = 0.0

        if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) {

            let pFactor = (100.0 + percentage) / 100.0

            let newRed = (red*pFactor).clamped(to: 0.0 ... 1.0)
            let newGreen = (green*pFactor).clamped(to: 0.0 ... 1.0)
            let newBlue = (blue*pFactor).clamped(to: 0.0 ... 1.0)

            return UIColor(red: newRed, green: newGreen, blue: newBlue, alpha: alpha)
        }

        return self
    }
}

Fonction de serrage Extension permettant de conserver facilement les valeurs entre min et max.

extension Comparable {

    func clamped(to range: ClosedRange<Self>) -> Self {

        if self > range.upperBound {
            return range.upperBound
        } else if self < range.lowerBound {
            return range.lowerBound
        } else {
            return self
        }
    }
}

2voto

ChrisDL Points 21

La réponse de Kenji-Tran fonctionne bien, tant que votre couleur de départ n'est pas le noir (valeur de luminosité 0). Avec l'ajout de quelques lignes de code supplémentaires, vous pouvez également rendre le noir plus "léger" (c'est-à-dire l'éclaircir à une valeur de niveau de gris ou de couleur).

Note : Je n'ai pas été en mesure d'ajouter cette modification en utilisant une édition et je ne suis pas autorisé à commenter la réponse de Kenji-Tran en raison de ma réputation de "nouveau garçon", donc je n'ai pas trouvé d'autre moyen de partager mes connaissances sur le SO que de poster une nouvelle réponse. J'espère que cela vous convient.

extension UIColor {
  /**
   Create a ligher color
   */
  func lighter(by percentage: CGFloat = 30.0) -> UIColor {
    return self.adjustBrightness(by: abs(percentage))
  }

  /**
   Create a darker color
   */
  func darker(by percentage: CGFloat = 30.0) -> UIColor {
    return self.adjustBrightness(by: -abs(percentage))
  }

  /**
   Try to increase brightness or decrease saturation
   */
  func adjustBrightness(by percentage: CGFloat = 30.0) -> UIColor {
    var h: CGFloat = 0, s: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
    if self.getHue(&h, saturation: &s, brightness: &b, alpha: &a) {
      if b < 1.0 {
        /**
         Below is the new part, which makes the code work with black as well as colors
        */
        let newB: CGFloat
        if b == 0.0 {
            newB = max(min(b + percentage/100, 1.0), 0.0)
        } else {
            newB = max(min(b + (percentage/100.0)*b, 1.0), 0,0)
        }
        return UIColor(hue: h, saturation: s, brightness: newB, alpha: a)
      } else {
        let newS: CGFloat = min(max(s - (percentage/100.0)*s, 0.0), 1.0)
        return UIColor(hue: h, saturation: newS, brightness: b, alpha: a)
      }
    }
    return self
  }
}

0 votes

Merci d'avoir signalé la case manquante (y). Puis-je poser une question ? Pourquoi est-ce que b == 0.0 && s == 0.0 ? Je pensais que vous vouliez juste plus de cas b == 0 est suffisant pour résoudre le problème. Car si b is 0 and s > 0 votre code n'est toujours pas capable de rendre la couleur plus claire ?

0 votes

Bonne question. C'est une erreur. J'ai corrigé le code. La raison pour laquelle j'ai vérifié si s == 0 c'est parce que je voulais que ça fonctionne du noir aux niveaux de gris. Mais évidemment, sans le s == 0 cela fonctionne pour toute couleur avec une luminosité de zéro. Merci.

0voto

Microbob Points 86

Testé dans Xcode 10 avec Swift 4.x pour iOS 12

Commencez avec votre couleur sous forme de UIColor et choisissez un facteur d'assombrissement (sous forme de CGFloat).

let baseColor = UIColor.red
let darkenFactor: CGFloat = 2

Le type CGColor a une valeur optionnelle components qui décompose la couleur en RGBA (comme un tableau CGFloat avec des valeurs entre 0 et 1). Vous pouvez ensuite reconstruire une UIColor en utilisant les valeurs RGBA extraites de CGColor et les manipuler.

let darkenedBase = UIColor(displayP3Red: startColor.cgColor.components![0] / darkenFactor, green: startColor.cgColor.components![1] / darkenFactor, blue: startColor.cgColor.components![2] / darkenFactor, alpha: 1)

Dans cet exemple, chacune des valeurs RVB a été divisée par 2, ce qui rend la couleur moitié moins foncée qu'auparavant. La valeur alpha est restée la même, mais vous pourriez aussi appliquer le facteur d'assombrissement sur la valeur alpha plutôt que sur la valeur RVB.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X