Если вы хотите передать какой-либо цвет, а затем определить, какой цвет текста будет более идеальным - черный или белый, - вам сначала нужно определить яркость этого цвета (в 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
с белым. Итак, ясно, что мы должны использовать черный цвет в качестве цвета шрифта!
Значение черного можно подтвердить здесь < / а>.
РЕДАКТИРОВАТЬ: Логика для .controlTextColor
будет лежать под поверхностью API, предоставляемого Apple, и вне меня. Это связано с предпочтениями пользователя и т. Д. И может работать с представлениями во время выполнения (т.е., задав .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
.
person
jake
schedule
09.06.2019
labelColor
и многие другие системные цвета теперь являются динамическими цветами; они меняются в зависимости от режима отображения вида / окна / экрана / системы. Я подозреваю, что вам придется создать свой собственный подкласс NSColor для достижения аналогичного эффекта, и я рискну предположить, что это будет нетривиальная задача. - person James Bucanek   schedule 09.05.2019