我正在开发可可应用程序,我发现只要将NSTextField的字体颜色设置为NSColor。 labelColor,字体将根据NSTextField的背景颜色而改变。
例如,当我将背景色设置为白色时,字体变为黑色。
但是当我将背景色设置为黑色时,字体变成白色。
我想定义一个NSColor来达到相同的效果。如何实现?
答案 0 :(得分:3)
如果要传递任何颜色,然后确定哪种文本颜色更理想-黑色或白色-首先需要确定该颜色的亮度(以sRGB为单位)。为此,我们可以先转换为灰度,然后检查黑色与白色之间的对比度。
请查看此整洁的扩展程序:
extension NSColor {
/// Determine the sRGB luminance value by converting to grayscale. Returns a floating point value between 0 (black) and 1 (white).
func luminance() -> CGFloat {
var colors: [CGFloat] = [redComponent, greenComponent, blueComponent].map({ value in
if value <= 0.03928 {
return value / 12.92
} else {
return pow((value + 0.055) / 1.055, 2.4)
}
})
let red = colors[0] * 0.2126
let green = colors[1] * 0.7152
let blue = colors[2] * 0.0722
return red + green + blue
}
func contrast(with color: NSColor) -> CGFloat {
return (self.luminance() + 0.05) / (color.luminance() + 0.05)
}
}
现在,我们可以通过检查黑色背景色与白色之间的对比,来确定是否应使用黑色或白色作为文本。
// Background color for whatever UI component you want.
let backgroundColor = NSColor(red: 0.5, green: 0.8, blue: 0.2, alpha: 1.0)
// Contrast of that color w/ black.
let blackContrast = backgroundColor.contrast(with: NSColor.black.usingColorSpace(NSColorSpace.sRGB)!)
// Contrast of that color with white.
let whiteContrast = backgroundColor.contrast(with: NSColor.white.usingColorSpace(NSColorSpace.sRGB)!)
// Ideal color of the text, based on which has the greater contrast.
let textColor: NSColor = blackContrast > whiteContrast ? .black : .white
在上述情况下,backgroundColor
与黑色产生10.595052467245562
和白色与0.5045263079640744
形成对比。很明显,我们应该使用黑色作为字体颜色!
可以证实here是黑色的值。
编辑:.controlTextColor
的逻辑将在Apple提供的API的范围之内,而超出我的范围。它与用户的偏好设置等有关,并且可能在运行时对视图进行操作(即,通过设置.controlTextColor
,您可能会标记一个视图以检查哪个textColor
在运行时更容易识别并应用它)。
TL; DR:我认为您无法通过.controlTextColor
子类获得与NSColor
相同的效果。
下面是一个子类元素的示例,该元素使用其backgroundColor
来确定textColor
,以实现相同的效果。根据您对课程应用的backgroundColor
,textColor
将由它决定。
class ContrastTextField: NSTextField {
override var textColor: NSColor? {
set {}
get {
if let background = self.layer?.backgroundColor {
let color = NSColor(cgColor: background)!.usingColorSpace(NSColorSpace.sRGB)!
let blackContrast = color.contrast(with: NSColor.black.usingColorSpace(NSColorSpace.sRGB)!)
let whiteContrast = color.contrast(with: NSColor.white.usingColorSpace(NSColorSpace.sRGB)!)
return blackContrast > whiteContrast ? .black : .white
}
return NSColor.black
}
}
}
然后您可以通过以下方式实现:
let textField = ContrastTextField()
textField.wantsLayer = true
textField.layer?.backgroundColor = NSColor.red.cgColor
textField.stringValue = "test"
将根据textColor
的背景来设置layer
。