web-dev-qa-db-fra.com

Obtenez une couleur légèrement plus claire et plus foncée de UIColor

Je cherchais à transformer n'importe quel UIColor en dégradé. Pour ce faire, j'utilise Core Graphics pour dessiner un dégradé. Ce que j'essaie de faire est d'obtenir une couleur, disons:

[UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];

et obtenez un UIColor qui est quelques nuances plus sombres et quelques nuances plus claires. Est-ce que quelqu'un sait comment faire ça? Je vous remercie.

139
CoreCode
- (UIColor *)lighterColorForColor:(UIColor *)c
{
    CGFloat r, g, b, a;
    if ([c getRed:&r green:&g blue:&b alpha:&a])
        return [UIColor colorWithRed:MIN(r + 0.2, 1.0)
                               green:MIN(g + 0.2, 1.0)
                                blue:MIN(b + 0.2, 1.0)
                               alpha:a];
    return nil;
}

- (UIColor *)darkerColorForColor:(UIColor *)c
{
    CGFloat r, g, b, a;
    if ([c getRed:&r green:&g blue:&b alpha:&a])
        return [UIColor colorWithRed:MAX(r - 0.2, 0.0)
                               green:MAX(g - 0.2, 0.0)
                                blue:MAX(b - 0.2, 0.0)
                               alpha:a];
    return nil;
}

Utilisez-le comme ceci:

UIColor *baseColor = // however you obtain your color
UIColor *lighterColor = [self lighterColorForColor:baseColor];
UIColor *darkerColor = [self darkerColorForColor:baseColor];

EDIT: comme l'a souligné @Anchu Chimala, pour une flexibilité maximale, ces méthodes doivent être implémentées en tant que catégorie UIColor. De plus, selon l'idée de @ Riley, il peut être préférable de rendre la couleur plus foncée ou plus claire, au lieu d'ajouter ou de soustraire des valeurs constantes. Comme @jrturton l'a souligné, il n'est pas nécessaire de manipuler les composants RVB; il est préférable de modifier la propriété de luminosité elle-même. En tout:

@implementation UIColor (LightAndDark)

- (UIColor *)lighterColor
{
    CGFloat h, s, b, a;
    if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
        return [UIColor colorWithHue:h
                          saturation:s
                          brightness:MIN(b * 1.3, 1.0)
                               alpha:a];
    return nil;
}

- (UIColor *)darkerColor
{
    CGFloat h, s, b, a;
    if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
        return [UIColor colorWithHue:h
                          saturation:s
                          brightness:b * 0.75
                               alpha:a];
    return nil;
}
@end
273
user529758

TL; DR:

Rapide:

extension UIColor {

    var lighterColor: UIColor {
        return lighterColor(removeSaturation: 0.5, resultAlpha: -1)
    }

    func lighterColor(removeSaturation val: CGFloat, resultAlpha alpha: CGFloat) -> UIColor {
        var h: CGFloat = 0, s: CGFloat = 0
        var b: CGFloat = 0, a: CGFloat = 0

        guard getHue(&h, saturation: &s, brightness: &b, alpha: &a)
            else {return self}

        return UIColor(hue: h,
                       saturation: max(s - val, 0.0),
                       brightness: b,
                       alpha: alpha == -1 ? a : alpha)
    }
}

Usage:

let lightColor = somethingDark.lighterColor

Objectif c:

- (UIColor *)lighterColorRemoveSaturation:(CGFloat)removeS
                              resultAlpha:(CGFloat)alpha {
    CGFloat h,s,b,a;
    if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) {
        return [UIColor colorWithHue:h
                          saturation:MAX(s - removeS, 0.0)
                          brightness:b
                               alpha:alpha == -1? a:alpha];
    }
    return nil;
}

- (UIColor *)lighterColor {
    return [self lighterColorRemoveSaturation:0.5
                                  resultAlpha:-1];
}

@rchampourlier avait raison dans son commentaire sur @ user529758 (la réponse acceptée) - Les solutions HSB (ou HSV) et RVB donnent des résultats complètement différents. RVB ajoute simplement (ou rapproche la couleur du) blanc, et la solution HSB rapproche la couleur de l’Edge dans l’échelle Brigtness - qui commence essentiellement par le noir et se termine par la couleur pure ...

En gros, la luminosité (valeur) rend la couleur plus ou moins proche du noir, tandis que la saturation la rend plus ou moins proche du blanc ... 

Comme on le voit ici:

HSV color graph

Donc la solution pour rendre une couleur réellement plus lumineuse (c'est-à-dire plus proche du blanc ...) sera de rendre sa valeur de saturation plus petite , ce qui donne cette solution

- (UIColor *)lighterColor {
    CGFloat h,s,b,a;
    if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) {
        return [UIColor colorWithHue:h
                          saturation:MAX(s - 0.3, 0.0)
                          brightness:b /*MIN(b * 1.3, 1.0)*/
                               alpha:a];
    }
    return nil;
}
51
Aviel Gross

Swift extension universelle pour iOS et OS X , utilisation de getHue :

#if os(OSX)

    import Cocoa
    public  typealias PXColor = NSColor

    #else

    import UIKit
    public  typealias PXColor = UIColor

#endif

    extension PXColor {

    func lighter(amount : CGFloat = 0.25) -> PXColor {
        return hueColorWithBrightnessAmount(1 + amount)
    }

    func darker(amount : CGFloat = 0.25) -> PXColor {
        return hueColorWithBrightnessAmount(1 - amount)
    }

    private func hueColorWithBrightnessAmount(amount: CGFloat) -> PXColor {
        var hue         : CGFloat = 0
        var saturation  : CGFloat = 0
        var brightness  : CGFloat = 0
        var alpha       : CGFloat = 0

        #if os(iOS)

            if getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) {
                return PXColor( hue: hue,
                                saturation: saturation,
                                brightness: brightness * amount,
                                alpha: alpha )
            } else {
                return self
            }

            #else

            getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
            return PXColor( hue: hue,
                            saturation: saturation,
                            brightness: brightness * amount,
                            alpha: alpha )

        #endif

    }

}

Utilisation: 

let color = UIColor(red: 0.5, green: 0.8, blue: 0.8, alpha: 1.0)
color.lighter(amount:0.5)
color.darker(amount:0.5)

OU (avec les valeurs par défaut):

color.lighter()
color.darker()

Échantillon : 

enter image description here

37
CryingHippo

La solution de user529758 dans Swift:  

Couleur plus sombre:

func darkerColorForColor(color: UIColor) -> UIColor {

       var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0

       if color.getRed(&r, green: &g, blue: &b, alpha: &a){
           return UIColor(red: max(r - 0.2, 0.0), green: max(g - 0.2, 0.0), blue: max(b - 0.2, 0.0), alpha: a)
       }

       return UIColor()
}

Couleur plus claire:

func lighterColorForColor(color: UIColor) -> UIColor {

       var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0

       if color.getRed(&r, green: &g, blue: &b, alpha: &a){
           return UIColor(red: min(r + 0.2, 1.0), green: min(g + 0.2, 1.0), blue: min(b + 0.2, 1.0), alpha: a)
       }

       return UIColor()
}
23
Sebyddd

Je voulais juste donner le même résultat, en RVB, que

  • placer la couleur avec alpha x% sur un fond blanc pour éclaircir
  • placer la couleur avec alpha x% sur un fond noir pour l'assombrir

Ce qui donne le même résultat, autant que je sache, est de choisir la couleur dans un dégradé "couleur au blanc" ou "couleur au noir", à x% de la taille du dégradé.

Pour cela, le calcul est simple:

// UIColor+Mix.Swift
import UIKit
extension UIColor {

    func mixLighter (amount: CGFloat = 0.25) -> UIColor {
        return mixWithColor(UIColor.whiteColor(), amount:amount)
    }

    func mixDarker (amount: CGFloat = 0.25) -> UIColor {
        return mixWithColor(UIColor.blackColor(), amount:amount)
    }

    func mixWithColor(color: UIColor, amount: CGFloat = 0.25) -> UIColor {
        var r1     : CGFloat = 0
        var g1     : CGFloat = 0
        var b1     : CGFloat = 0
        var alpha1 : CGFloat = 0
        var r2     : CGFloat = 0
        var g2     : CGFloat = 0
        var b2     : CGFloat = 0
        var alpha2 : CGFloat = 0

        self.getRed (&r1, green: &g1, blue: &b1, alpha: &alpha1)
        color.getRed(&r2, green: &g2, blue: &b2, alpha: &alpha2)
        return UIColor( red:r1*(1.0-amount)+r2*amount,
                        green:g1*(1.0-amount)+g2*amount,
                        blue:b1*(1.0-amount)+b2*amount,
                        alpha: alpha1 )
    }
}

Voici des exemples avec quelques couleurs

 Examples Darker and Lighter

19
FredericP

Si vous convertissez la couleur RVB en modèle de couleur HSL , vous pouvez faire varier la composante L = luminosité de L = 0.0 (noir) sur L = 0.5 (couleur naturelle) à L = 1.0 (blanc). UIColor ne peut pas gérer HSL directement, mais il existe une formule pour convertir RGB <-> HSL. 

13
Martin R

Aucune des solutions publiées quite n'a fonctionné pour toutes les couleurs et toutes les nuances, mais je suis tombé par hasard sur cette bibliothèque qui fournit un ensemble d'extensions très bien implémentées d'UIColor. 

Plus précisément, il a une fonction allégée dans son implémentation HSL: (UIColor *)lighten:(CGFloat)amount - qui fonctionne parfaitement.

6
Terminus

Extension UIColor et fixation de lighterColorForColor

extension UIColor {
  class func darkerColorForColor(color: UIColor) -> UIColor {
    var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
    if color.getRed(&r, green: &g, blue: &b, alpha: &a){
      return UIColor(red: max(r - 0.2, 0.0), green: max(g - 0.2, 0.0), blue: max(b - 0.2, 0.0), alpha: a)
    }
    return UIColor()
  }

  class func lighterColorForColor(color: UIColor) -> UIColor {
    var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
    if color.getRed(&r, green: &g, blue: &b, alpha: &a){
      let tmpColor = UIColor(red: min(r + 0.2, 1.0), green: min(g + 0.2, 1.0), blue: min(b + 0.2, 1.0), alpha: a)
      println(tmpColor)
      return tmpColor
    }
    return UIColor()
  }
}
2
Justin Levi Winter

Sebyddd solution en extension:

extension UIColor {    
    func darker() -> UIColor {

        var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0

        if self.getRed(&r, green: &g, blue: &b, alpha: &a){
            return UIColor(red: max(r - 0.2, 0.0), green: max(g - 0.2, 0.0), blue: max(b - 0.2, 0.0), alpha: a)
        }

        return UIColor()
    }

    func lighter() -> UIColor {

        var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0

        if self.getRed(&r, green: &g, blue: &b, alpha: &a){
            return UIColor(red: min(r + 0.2, 1.0), green: min(g + 0.2, 1.0), blue: min(b + 0.2, 1.0), alpha: a)
        }

        return UIColor()
    }
}

Utilisation:

let darkerYellow = UIColor.yellow.darker()
let lighterYellow = UIColor.yellow.lighter()
2
Hemang

Toutes les autres réponses de ce fil de discussion utilisent soit le système de couleurs RVB ou changez simplement la valeur valeur de teinte ou de luminosité du système HSB. Comme expliqué en détail dans ce blog génial , le moyen correct de rendre une couleur plus claire ou plus sombre consiste à changer sa valeur luminance. Aucune des autres réponses ne le fait. Si vous voulez bien faire les choses, alors utilisez ma solution ou écrivez vous-même après avoir lu l'article du blog.


Malheureusement, il est assez compliqué de modifier l’un des attributs d’un UIColor par défaut. De plus, Apple ne prend en charge aucun espace colorimétrique basé sur LAB tel que HCL dans la classe UIColor (la L dans LAB est la valeur luminance que nous recherchons).

Utiliser HandyUIKit (l'installer via Carthage) ajoute le support pour HCL et vous rend la vie beaucoup plus facile:

import HandyUIKit    

let color = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1.0)

// create a new UIColor object with a specific luminance (slightly lighter)
color.change(.luminance, to: 0.7)

Il existe également une option pour appliquer un changement relatif (recommandé):

// create a new UIColor object with slightly darker color
color.change(.luminance, by: -0.2)

Notez que HandyUIKit ajoute également certaines autres fonctionnalités de l’interface utilisateur très utiles à votre projet - vérifiez son README sur GitHub pour plus de détails.

J'espère que ça aide!

2
Dschee

Si vous voulez que la solution de user529758 fonctionne avec des nuances de gris (comme [UIColor lightGrayColor] ou [UIColor darkGrayColor], vous devez l'améliorer de la manière suivante: 

- (UIColor *)lighterColor
{
    CGFloat h, s, b, a;
    if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) {
        return [UIColor colorWithHue:h
                          saturation:s
                          brightness:MIN(b * 1.3, 1.0)
                               alpha:a];
    }

    CGFloat white, alpha;
    if ([self getWhite:&white alpha:&alpha]) {
        white = MIN(1.3*white, 1.0);
        return [UIColor colorWithWhite:white alpha:alpha];
    }

    return nil;
}

getHue:saturation:brightness:alpha échoue (et retourne false) lorsqu'il est appelé sur une teinte grise; vous devez donc utiliser getWhite:alpha

2
Matthieu Riegler

Je ne sais pas si vous cherchez une réponse à Objective-C, mais en fonction du fonctionnement des couleurs spécifiées par RGBA, je pense que vous pouvez simplement redimensionner les valeurs RVB selon un facteur arbitraire pour obtenir un "plus clair" ou "plus sombre" ombre. Par exemple, vous pourriez avoir un bleu:

[UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0];

Vous voulez un bleu plus foncé? Multipliez les valeurs RVB par 0,9:

[UIColor colorWithRed:0.0 green:0.0 blue:0.9 alpha:1.0];

Voila. Ou peut-être que vous avez une orange:

[UIColor colorWithRed:1.0 green:0.4 blue:0.0 alpha:1.0];

Choisissez un autre facteur d'échelle, par exemple 0.8:

[UIColor colorWithRed:0.8 green:0.32 blue:0.0 alpha:1.0];

Est-ce le genre d'effet que vous recherchez?

1
ravron

Idéalement, les fonctions doivent être encapsulées dans une extension UIColor appelée UIColor+Brightness.Swift et avoir une luminosité configurable - voir l'exemple ci-dessous:

import UIKit

extension UIColor {

  func lighterColorWithBrightnessFactor(brightnessFactor:CGFloat) -> UIColor {
    var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
    if self.getRed(&r, green:&g, blue:&b, alpha:&a) {
      return UIColor(red:min(r + brightnessFactor, 1.0),
        green:min(g + brightnessFactor, 1.0),
        blue:min(b + brightnessFactor, 1.0),
        alpha:a)
    }
    return UIColor()
  }

}
0
Zorayr

Voici une catégorie UIColor qui permet également de contrôler la quantité de changement de couleur.

- (UIColor *)lighterColorWithDelta:(CGFloat)delta
{
    CGFloat r, g, b, a;
    if ([self getRed:&r green:&g blue:&b alpha:&a])
        return [UIColor colorWithRed:MIN(r + delta, 1.0)
                               green:MIN(g + delta, 1.0)
                                blue:MIN(b + delta, 1.0)
                               alpha:a];
    return nil;
}

- (UIColor *)darkerColorWithDelta:(CGFloat)delta
{
    CGFloat r, g, b, a;
    if ([self getRed:&r green:&g blue:&b alpha:&a])
        return [UIColor colorWithRed:MAX(r - delta, 0.0)
                               green:MAX(g - delta, 0.0)
                                blue:MAX(b - delta, 0.0)
                               alpha:a];
    return nil;
}
0
Blago

Une extension Swift basée sur @Sebyddd answer:

import Foundation
import UIKit

extension UIColor{
    func colorWith(brightness: CGFloat) -> UIColor{
        var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0

        if getRed(&r, green: &g, blue: &b, alpha: &a){
            return UIColor(red: max(r + brightness, 0.0), green: max(g + brightness, 0.0), blue: max(b + brightness, 0.0), alpha: a)
        }

        return UIColor()
    }
}
0
Balázs Vincze

pour les couleurs plus sombres, c'est le plus simple: theColor = [theColor shadowWithLevel: s]; //s:0.0 à 1.0

0
Jiulong Zhao

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

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

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

Le type CGColor a une valeur optionnelle components qui décompose la couleur en RGBA (sous forme de tableau CGFloat avec des valeurs comprises 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 a rendu la couleur aussi sombre qu’elle l’était auparavant. La valeur alpha est restée la même, mais vous pouvez également appliquer le facteur d'assombrissement sur la valeur alpha plutôt que sur le RVB. 

0
Microbob

Je rend les cellules colorées en fonction d'une valeur de statut:

status-images

Pour cela, j'ai écrit une extension Swift basée sur un ancien code objc après une erreur en utilisant la suggestion de CryingHippo:

extension UIColor{

    func darker(darker: CGFloat) -> UIColor{

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

        if self.colorSpace == UIColorSpace.genericGrayColorSpace(){

            red =  whiteComponent - darker
            green = whiteComponent - darker
            blue  = whiteComponent - darker
        } else {
            red = redComponent - darker
            green = greenComponent - darker
            blue = blueComponent - darker
        }

        if red < 0{
            green += red/2
            blue += red/2
        }

        if green < 0{
            red += green/2
            blue += green/2
        }

        if blue < 0{
            green += blue/2
            red += blue/2
        }

        return UIColor(
            calibratedRed: red,
            green: green,
            blue: blue,
            alpha: alphaComponent
        )
    }

    func lighter(lighter: CGFloat) -> UIColor{
        return darker(-lighter)
    }
}

La même chose fonctionne pour NSColor également. Remplacez simplement UIColor par NSColor.

0
Besi