为给定的 UIColor 获取更亮和更暗的颜色变化
Posted
技术标签:
【中文标题】为给定的 UIColor 获取更亮和更暗的颜色变化【英文标题】:Get lighter and darker color variations for a given UIColor 【发布时间】:2016-11-20 23:27:59 【问题描述】:如何在 Swift 中获得给定 UIColor 的不同亮色和暗色变化?
【问题讨论】:
title 问题很简单,允许不同的解决方案;你也可以使用一个函数而不是两个使用负输入参数 这里***.com/questions/11598043/…提出了各种技术,Swift中也有答案。 @ShadowOf 已更新,感谢输入 Swift - 4.0 Click hare 回答 this answer 在您发布问题时已经可用。总的来说,我认为这个问题和其他问题非常相似,如果不重复的话。 【参考方案1】:更新
使用下面的UIColor扩展:
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
用法:
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%
除了.lighter()
和.darker()
,您可以使用.adjust()
,正值表示变亮,负值表示变暗
color.adjust(-30) // 30% darker color
color.adjust(30) // 30% lighter color
输出:
【讨论】:
您用相同的值修改所有组件,而不是按比例更改它们。看看当你把橙色调亮时,它是如何变成黄色的。 按比例添加值是不正确的。试试这个颜色 UIColor(red:0.89, green:0.28, blue:0.00, alpha:1.0) 但是向所有组件添加相同的值也不正确,它会改变颜色。查看***.com/questions/11598043/… 的各种答案,其中调整了 HSB 表示中的 brightness。 @MartinR 我已经执行了你的函数和我的函数,两个输出都是相同的(橙色没有变成黄色;-))。但是我需要提高技能以减少代码。我应该避免转换为 RGB 值并在单个函数中编写逻辑。将更新代码 我相信黑色打火机,返回绿色【参考方案2】:我想提供另一个使用亮度和饱和度而不是 RGB 的版本
extension UIColor
/**
Create a lighter 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
【讨论】:
我觉得这比修改RGB值好 当饱和度为 0 且亮度为 1.0 时,不要认为这有效。即白色。在这种情况下,您最终会得到不变的饱和度。 (不能使白色变亮。)这是正确的方法。 RGB 的答案在很多层面上都是完全错误的。 但是你可以使白色变暗(它应该变成灰色)但这不会这样做:/【参考方案3】:Kenji-Tran 的答案可以正常工作,只要您的起始颜色不是黑色(亮度值 0)。通过添加几行额外的代码,您还可以使黑色“更亮”(即将其变亮为灰度或颜色值)。
注意:我无法使用编辑添加此更改,并且由于我的“新男孩”代表,我无法评论 Kenji-Tran 的回答,因此我发现没有通过发布新答案来分享我对 SO 的知识的其他方式。我希望没关系。
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
【讨论】:
感谢您指出丢失的大小写 (y)。我可以问个问题吗?为什么是b == 0.0 && s == 0.0
?我认为只需要更多案例b == 0
就足以解决问题。因为如果b is 0 and s > 0
,你的代码还是不能让颜色变浅?
好问题。这是一个错误。我已经修复了代码。我检查s == 0
的原因是因为我希望它适用于黑色到灰度。但显然,如果没有s == 0
,它适用于任何亮度为零的颜色。谢谢。【参考方案4】:
修改 RGB 值的版本
在这里,我放置了简单的 UIColor
扩展名,它基于以前的答案。它对我来说非常有效。
下面的演示:
颜色操作代码
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
钳位功能 扩展以轻松保持最小值和最大值之间的值。
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
【讨论】:
【参考方案5】:使用 lukszar 钳位函数,我为 UIColor 扩展编写了这个函数,使用 RGB 值的真实比例。希望对你有帮助
public extension UIColor
public func lighter(by percentage: CGFloat = 30.0) -> UIColor
return self.adjustBrightness(by: abs(percentage))
public func darker(by percentage: CGFloat = 30.0) -> UIColor
return self.adjustBrightness(by: -abs(percentage))
func adjustBrightness(by percentage: CGFloat = 30.0) -> UIColor
let ratio = percentage/100
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 newRed = (red + ((ratio < 0) ? red * ratio : (1 - red) * ratio)).clamped(to: 0.0 ... 1.0)
let newGreen = (green + ((ratio < 0) ? green * ratio : (1 - green) * ratio)).clamped(to: 0.0 ... 1.0)
let newBlue = (blue + ((ratio < 0) ? blue * ratio : (1 - blue) * ratio)).clamped(to: 0.0 ... 1.0)
return UIColor(red: newRed, green: newGreen, blue: newBlue, alpha: alpha)
return self
【讨论】:
【参考方案6】:支持 RGBA、HSBA 和 WB(灰度)的 Swift 4 版本
这是 TranQuan 的 answer 的一个变体,它也支持像 .white
和 .black
这样的灰度颜色。 (注:我去掉了饱和度调整,因为我认为它不属于这样一个简单的功能。)
extension UIColor
/**
Create a ligher color
*/
func lighter(by percentage: CGFloat = 10.0) -> UIColor
return self.adjustBrightness(by: abs(percentage))
/**
Create a darker color
*/
func darker(by percentage: CGFloat = 10.0) -> UIColor
return self.adjustBrightness(by: -abs(percentage))
/**
Try to adjust brightness and falls back to adjusting colors if necessary
*/
func adjustBrightness(by percentage: CGFloat) -> UIColor
var alpha, hue, saturation, brightness, red, green, blue, white : CGFloat
(alpha, hue, saturation, brightness, red, green, blue, white) = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
let multiplier = percentage / 100.0
if self.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
let newBrightness: CGFloat = max(min(brightness + multiplier*brightness, 1.0), 0.0)
return UIColor(hue: hue, saturation: saturation, brightness: newBrightness, alpha: alpha)
else if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
let newRed: CGFloat = min(max(red + multiplier*red, 0.0), 1.0)
let newGreen: CGFloat = min(max(green + multiplier*green, 0.0), 1.0)
let newBlue: CGFloat = min(max(blue + multiplier*blue, 0.0), 1.0)
return UIColor(red: newRed, green: newGreen, blue: newBlue, alpha: alpha)
else if self.getWhite(&white, alpha: &alpha)
let newWhite: CGFloat = (white + multiplier*white)
return UIColor(white: newWhite, alpha: alpha)
return self
【讨论】:
这很好用,谢谢! 我实际上似乎无法增亮.black
或真正的深灰色,因此作为一种解决方法,我创建了另一个函数,该函数采用百分比并将颜色的亮度直接设置为该级别。问题在于公式:brightness + multiplier * brightness
,当亮度为 0 或非常小时,这不起作用。因此,您可以创建像这样的颜色 return UIColor(hue: hue, saturation: saturation, brightness: max(min(percentage / 100.0, 1.0), 0.0), alpha: alpha)
【参考方案7】:
对于 Swift 5.0:
extension UIColor
func lighter(by percentage: CGFloat = 10.0) -> UIColor
return self.adjust(by: abs(percentage))
func darker(by percentage: CGFloat = 10.0) -> UIColor
return self.adjust(by: -abs(percentage))
func adjust(by percentage: CGFloat) -> UIColor
var alpha, hue, saturation, brightness, red, green, blue, white : CGFloat
(alpha, hue, saturation, brightness, red, green, blue, white) = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
let multiplier = percentage / 100.0
if self.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
let newBrightness: CGFloat = max(min(brightness + multiplier*brightness, 1.0), 0.0)
return UIColor(hue: hue, saturation: saturation, brightness: newBrightness, alpha: alpha)
else if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
let newRed: CGFloat = min(max(red + multiplier*red, 0.0), 1.0)
let newGreen: CGFloat = min(max(green + multiplier*green, 0.0), 1.0)
let newBlue: CGFloat = min(max(blue + multiplier*blue, 0.0), 1.0)
return UIColor(red: newRed, green: newGreen, blue: newBlue, alpha: alpha)
else if self.getWhite(&white, alpha: &alpha)
let newWhite: CGFloat = (white + multiplier*white)
return UIColor(white: newWhite, alpha: alpha)
return self
【讨论】:
【参考方案8】:为了节省任何人打字,简单实用的版本只是
extension UIColor
var darker: UIColor
var h: CGFloat = 0, s: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
guard self.getHue(&h, saturation: &s, brightness: &b, alpha: &a) else
print("** some problem demuxing the color")
return .gray
let nudged = b * 0.5
return UIColor(hue: h, saturation: s, brightness: nudged, alpha: a)
使用喜欢
something.color = .yellow.darker
或
backgroundColor = backgroundColor.darker
在一个大型项目中......
您绝对应该扩展 Apple 的模式:
.withAlphaComponent(_ alpha: CGFloat)
所以,有:
.withBrightnessComponent(_ alpha: CGFloat)
很明显
.withBrightnessComponentAdjustedBy(percentage: CGFloat)
和/或
.withBrightnessComponentMultipliedBy(factor: CGFloat)
【讨论】:
【参考方案9】:下面的代码示例演示了如何获得给定颜色的较浅和较深的阴影,这在具有动态主题的应用程序中很有用
用于较深的颜色
+ (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)
return nil;
用于较浅的颜色
+ (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;
【讨论】:
【参考方案10】:SwiftUI:颜色 - ios 14 / macOS 10.16
extension Color
public func lighter(by amount: CGFloat = 0.2) -> Self Self(UIColor(self).lighter(by: amount))
public func darker(by amount: CGFloat = 0.2) -> Self Self(UIColor(self).darker(by: amount))
对于 iOS 或(和)macOS 需要以下之一(或两者)
AppKit:NSColor
extension NSColor
func mix(with color: NSColor, amount: CGFloat) -> Self
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 Self(
red: red1 * CGFloat(1.0 - amount) + red2 * amount,
green: green1 * CGFloat(1.0 - amount) + green2 * amount,
blue: blue1 * CGFloat(1.0 - amount) + blue2 * amount,
alpha: alpha1
)
func lighter(by amount: CGFloat = 0.2) -> Self mix(with: .white, amount: amount)
func darker(by amount: CGFloat = 0.2) -> Self mix(with: .black, amount: amount)
UIKit:UIColor
extension UIColor
func mix(with color: UIColor, amount: CGFloat) -> Self
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 Self(
red: red1 * CGFloat(1.0 - amount) + red2 * amount,
green: green1 * CGFloat(1.0 - amount) + green2 * amount,
blue: blue1 * CGFloat(1.0 - amount) + blue2 * amount,
alpha: alpha1
)
func lighter(by amount: CGFloat = 0.2) -> Self mix(with: .white, amount: amount)
func darker(by amount: CGFloat = 0.2) -> Self mix(with: .black, amount: amount)
【讨论】:
【参考方案11】:由于我在当前项目中使用 SwiftUI,因此我改编了 Stephen 的最佳答案。 使用 Xcode 12.0、SwiftUI 2 和 iOS 14.0 测试
extension Color
var components: (red: CGFloat, green: CGFloat, blue: CGFloat, opacity: CGFloat)
#if canImport(UIKit)
typealias NativeColor = UIColor
#elseif canImport(AppKit)
typealias NativeColor = NSColor
#endif
var r: CGFloat = 0
var g: CGFloat = 0
var b: CGFloat = 0
var o: CGFloat = 0
guard NativeColor(self).getRed(&r, green: &g, blue: &b, alpha: &o) else
return (0, 0, 0, 0)
return (r, g, b, o)
func lighter(by percentage: CGFloat = 30.0) -> Color
return self.adjust(by: abs(percentage) )
func darker(by percentage: CGFloat = 30.0) -> Color
return self.adjust(by: -1 * abs(percentage) )
func adjust(by percentage: CGFloat = 30.0) -> Color
return Color(red: min(Double(self.components.red + percentage/100), 1.0),
green: min(Double(self.components.green + percentage/100), 1.0),
blue: min(Double(self.components.blue + percentage/100), 1.0),
opacity: Double(self.components.opacity))
【讨论】:
【参考方案12】:对于macOS
应用程序,有一个用于颜色混合的内置功能。
要使颜色变浅,只需调用
NSColor.systemRed.blended(withFraction: 0.35, of: .white)
【讨论】:
【参考方案13】:我正在使用 SwiftUI,正在寻找快速解决方案。
此方法更改 Alpha 通道(0 是透明的,1 是不透明的)并将其置于白色视图的前面,因此您实际上是在将白色与颜色混合。 alpha 值越高,混入的白色越多 = 越亮。
将Color
转换为UIColor
、修改和转换回来就可以了:
Color(UIColor(Color.blue).withAlphaComponent(0.5))
.background(Color.white) // IMPORTANT: otherwise your view will be see-through
将颜色变暗 Color.white
到 Color.black
【讨论】:
以上是关于为给定的 UIColor 获取更亮和更暗的颜色变化的主要内容,如果未能解决你的问题,请参考以下文章