从UIColor获得略微更亮和更暗的颜色

时间:2012-07-22 05:50:12

标签: objective-c ios core-graphics gradient uicolor

我希望能够将任何UIColor变成渐变。我打算这样做的方法是使用Core Graphics绘制渐变。我想要做的是获得一种颜色,让我们说:

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

并获得一个UIColor,这是一些深色调和一些浅色调。有谁知道如何做到这一点?谢谢。

19 个答案:

答案 0 :(得分:274)

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

答案 1 :(得分:52)

TL; DR:

夫特:

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解决方案使颜色更接近Brigtness量表的边缘 - 基本上以黑色开始并以纯色结束......

基本上亮度(值)使颜色越来越接近黑色,饱和度使得它越来越接近白色......

如下所示:

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

答案 2 :(得分:37)

使用 getHue

Swift iOS和OS X 的通用扩展程序:

#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

答案 3 :(得分:23)

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

答案 4 :(得分:22)

我只想以RGB格式给出与

相同的结果
  • 将alpha x%的颜色放在白色背景上以使其变亮
  • 将alpha x%的颜色放在黑色背景上以使其变暗

其结果与AFAIK相同,而不是以渐变颜色选择颜色为白色'或者'颜色为黑色',在渐变尺寸的x%处。

为此目的,数学很简单:

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

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

    func mixDarker (amount: CGFloat = 0.25) -> UIColor {
        return mixWithColor(UIColor.black, 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 )
    }
}

以下是一些颜色的示例

Examples Darker and Lighter

答案 5 :(得分:13)

如果将RGB颜色转换为HSL color model,则可以将L =亮度分量从L = 0.0(黑色)变为L = 0.5(自然色)到L = 1.0(白色)。 UIColor无法直接处理HSL,但是存在用于转换RGB< - >的公式。 HSL。

答案 6 :(得分:6)

相当的所有解决方案都没有适用于所有颜色和阴影,但后来偶然发现了this library,它为UIColor提供了一组非常好的实现扩展。

具体来说,它有一个减轻功能作为其HSL实现的一部分:(UIColor *)lighten:(CGFloat)amount - 它完美地运作。

答案 7 :(得分:3)

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

答案 8 :(得分:2)

如果您希望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

答案 9 :(得分:2)

UIColor扩展并修复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()
  }
}

答案 10 :(得分:2)

此主题中的所有其他答案都使用 RGB颜色系统或只是更改HSB系统的色调或亮度值。正如在this great blog post中详细解释的那样,正确使颜色变浅或变暗的方法是更改​​其luminance值。没有其他答案那样做。如果你想做得对,那么在阅读博文后,使用我的解决方案编写自己的

不幸的是,默认情况下更改UIColor 的任何属性非常麻烦 。此外,Apple甚至不支持UIColor类中的任何基于LAB的色彩空间,例如HCL(LAB中的L是我们正在寻找的luminance值。

使用 HandyUIKit (通过Carthage安装)增加对 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还会在项目中添加其他一些方便的用户界面功能 - 请查看其README on GitHub了解更多详情。

我希望它有所帮助!

答案 11 :(得分:2)

快捷键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
     }
   }
}

答案 12 :(得分:1)

我不确定你是否在寻找某种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];

这是你正在寻找的那种效果吗?

答案 13 :(得分:1)

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

以您的颜色作为UIColor并选择一个变暗的因子(作为CGFloat)

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

类型CGColor具有可选值components,该值将颜色分解为RGBA(作为CGFloat数组,其值在0到1之间)。然后,您可以使用从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上应用变暗因子。

答案 14 :(得分:0)

理想情况下,这些函数应封装在名为UIColor的{​​{1}}扩展名中,并具有可配置的亮度 - 请参阅下面的示例:

UIColor+Brightness.swift

答案 15 :(得分:0)

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

status-images

为此,我在使用CryingHippo的建议收到错误后根据一些旧的objc代码写了一个swift扩展:

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

答案 16 :(得分:0)

这是一个UIColor类别,它还允许控制颜色变化量。

{{1}}

答案 17 :(得分:0)

基于@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()
    }
}

答案 18 :(得分:-1)

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

相关问题