从 UIColor 获得稍微亮一点和深一点的颜色

我希望能够把任何 UIColor 变成一个渐变。我打算这样做的方式是通过使用核心图形绘制梯度。我要做的是得到一个颜色,让我们说:

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

然后得到一个 UIColor,它有几种深浅不同的颜色,还有几种浅浅不同的颜色。有人知道怎么做吗?谢谢你。

61760 次浏览

我不确定您是否在寻找某种 Objective-C 的答案,但是基于 RGBA 指定的颜色的工作方式,我认为您可以简单地根据任意因素来缩放 RGB 值,以获得“更亮”或“更暗”的颜色。例如,您可能有一个蓝色:

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

想要更深的蓝色? 将 RGB 值乘以0.9:

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

瞧,或者你有一个橙子:

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

选择另一个比例因子,比如0.8:

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

这就是你想要的效果吗?

- (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;
}

像这样使用它:

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

编辑 : 正如@Anchu Chimala 指出的,为了获得最大的灵活性,这些方法应该作为 UIColor 类别实现。此外,根据@Riley 的想法,可能更好的办法是使颜色按比例变深或变浅,而不是增加或减少常量值。正如@jrturton 指出的,没有必要操作 RGB 组件; 最好修改亮度属性本身。总而言之:

@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

如果您将 RGB 颜色转换为 彩色模型,那么您可以将 L = 亮度分量从 L = 0.0(黑色)改为 L = 0.5(自然色)到 L = 1.0(白色)。UIColor不能直接处理 HSL,但有转换 RGB <-> HSL 的公式。

译者:

斯威夫特:

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

用法:

let lightColor = somethingDark.lighterColor

目标 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 在他给@user529758的评论中是正确的(公认的答案)—— HSB (或 HSV)和 RGB 解决方案给出了完全不同的结果。RGB 只是增加(或使颜色更接近)白色,HSB 解决方案使颜色更接近边缘的亮度规模-这基本上开始与黑色和结束与纯色..。

基本上亮度(值)使颜色更少或更接近黑色,饱和度使它更少或更接近白色..。

如图所示:

HSV color graph

因此,让颜色更明亮(比如更接近白色...)的解决方案将是使其饱和度值 更小,结果如下:

- (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;
}

如果你想让 user529758的解决方案使用灰色阴影(如 [UIColor lightGrayColor][UIColor darkGrayColor],你必须这样改进它:

- (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失败(并返回 false) ,因此需要使用 getWhite:alpha

没有一个解决方案公布的 没错工作的所有颜色和阴影,但后来我偶然发现了 这个图书馆,它提供了一套非常好的实现扩展 UIColor。

具体来说,它在 HSL 实现中有一个减轻负担的功能: (UIColor *)lighten:(CGFloat)amount——它工作得很完美。

用户529758在 Swift 中的解决方案:

深色:

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

浅色:

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

颜色扩展和固定打火机

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

理想情况下,这些函数应该封装在一个名为 UIColor+Brightness.swiftUIColor扩展中,并具有可配置的亮度——见下面的例子:

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


}

Swift IOS 和 OSX的通用扩展,使用 快点:

#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


}


}

用法:

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)

OR (使用默认值) :

color.lighter()
color.darker()

样本:

enter image description here

我根据状态值渲染彩色单元格:

status-images

为此,在使用 CryingHippo 的建议得到一个错误后,我基于一些旧的 objecc 代码编写了一个快速扩展:

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

同样的原理也适用于 NSColor,只需将 UIColor替换为 NSColor即可。

我只是想给出相同的结果,在 RGB,比

  • 将 alpha x% 的颜色置于白色背景上以减轻色调
  • 将 alpha x% 的颜色放置在黑色背景上使其变暗

AFAIK,这与在渐变大小的 x% 下选择“颜色到白色”或“颜色到黑色”渐变的颜色得到的结果是一样的。

为此,计算很简单:

extension UIColor {
func mix(with color: UIColor, amount: CGFloat) -> UIColor {
var red1: CGFloat = 0
var green1: CGFloat = 0
var blue1: CGFloat = 0
var alpha1: CGFloat = 0


var red2: CGFloat = 0
var green2: CGFloat = 0
var blue2: CGFloat = 0
var alpha2: CGFloat = 0


getRed(&red1, green: &green1, blue: &blue1, alpha: &alpha1)
color.getRed(&red2, green: &green2, blue: &blue2, alpha: &alpha2)


return UIColor(
red: red1 * (1.0 - amount) + red2 * amount,
green: green1 * (1.0 - amount) + green2 * amount,
blue: blue1 * (1.0 - amount) + blue2 * amount,
alpha: alpha1
)
}
}

下面是一些带有颜色的例子

Examples Darker and Lighter

该线程中的所有其他答案都使用 要么是 RGB 颜色系统或者只是更改 HSB 系统的色调或亮度值。正如在 < strong > 这篇伟大的博客文章 中详细解释的那样,正确使颜色变浅或变深的方法是改变它的 luminance值。其他答案都不会这样。如果你想做的正确,然后 用我的方法自己写后,阅读博客文章。


不幸的是,真麻烦可以更改 UIColor 默认情况下的任何属性。此外,苹果甚至不支持任何基于实验室的颜色空间,如 HCL 在 UIColor类(L在实验室是 luminance值,我们正在寻找)。

使用 一个 href = “ https://github.com/Flinesoft/HandyUIKit”rel = “ norefrer”> HandyUIKit (通过迦太基安装)增加了对 HCL的支持,使你的生活 简单多了:

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)

还有一个选项是应用 相对变化(建议) :

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

请注意,HandyUIKit 还将 一些其他方便的用户界面特性添加到您的项目中——查看其 GitHub 上的自述以获得更多细节。

希望能有所帮助!

免责声明: 我是 HandyUIKit 的作者。

作为扩展的 Sebyddd解决方案:

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

用法:

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

下面是一个 UIColor 类别,它还允许控制颜色变化的数量。

- (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;
}

基于@Sebyddd 的 Swift 扩展:

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

在 Xcode 10中对 iOS 12的 Swift 4.x 进行了测试

从 UIColor 的颜色开始,选择一个暗化因子(CGFloat)

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

CGColor 类型有一个可选的值 components,它将颜色分解为 RGBA (作为一个值介于0和1之间的 CGFloat 数组)。然后可以使用从 CGColor 获取的 RGBA 值重新构建 UIColor 并操作它们。

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

在这个示例中,每个 RGB 值除以2,使颜色只有原来的一半深。Alpha 值保持不变,但是您可以选择在 alpha 值上应用暗因子,而不是 RGB。

对于较深的颜色,这是最简单的: TheColor = [ theColor ShadowWithLevel: s ] ;//s: 0.0 to 1.0

Swift 5

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 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 + percentage/100, 1.0),
green: min(g + percentage/100, 1.0),
blue: min(b + percentage/100, 1.0),
alpha: a)
} else {
return nil
}
}
}