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.
- (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
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
- (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:
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;
}
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 :
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()
}
Je voulais juste donner le même résultat, en RVB, que
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
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.
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.
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()
}
}
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()
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!
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
.
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?
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()
}
}
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;
}
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()
}
}
pour les couleurs plus sombres, c'est le plus simple: theColor = [theColor shadowWithLevel: s]; //s:0.0 à 1.0
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.
Je rend les cellules colorées en fonction d'une valeur de statut:
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
.