Created
October 13, 2018 02:33
-
-
Save elnjensen/e7b649e83b6213f9fbe8e503d59f98a8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
// Extension from lkoskela, https://gist.github.com/lkoskela/c06670ded4d01a1832bd90066e76a0a8 | |
extension UIColor { | |
/// Relative luminance of a color according to W3's WCAG 2.0: | |
/// https://www.w3.org/TR/WCAG20/#relativeluminancedef | |
var luminance: CGFloat { | |
var red: CGFloat = 0 | |
var green: CGFloat = 0 | |
var blue: CGFloat = 0 | |
var alpha: CGFloat = 0 | |
self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) | |
return 0.2126 * red + 0.7152 * green + 0.0722 * blue | |
} | |
/// Contrast ratio between two colors according to W3's WCAG 2.0: | |
/// https://www.w3.org/TR/WCAG20/#contrast-ratiodef | |
func contrastRatio(to otherColor: UIColor) -> CGFloat { | |
let ourLuminance = self.luminance | |
let theirLuminance = otherColor.luminance | |
let lighterColor = min(ourLuminance, theirLuminance) | |
let darkerColor = max(ourLuminance, theirLuminance) | |
return 1 / ((lighterColor + 0.05) / (darkerColor + 0.05)) | |
} | |
/// Determines whether the contrast between this `UIColor` and the provided | |
/// `UIColor` is sufficient to meet the recommendations of W3's WCAG 2.0. | |
/// | |
/// The recommendation is that the contrast ratio between text and its | |
/// background should be at least 4.5:1 for small text and at least | |
/// 3.0:1 for larger text. | |
func sufficientContrast(to otherColor: UIColor) -> Bool { | |
let contrastRatioThreshold: CGFloat = 3.0 | |
return contrastRatio(to: otherColor) > contrastRatioThreshold | |
} | |
} | |
// Colors from Loop: | |
extension UIColor { | |
static let tintColor = UIColor(red: 76 / 255, green: 217 / 255, blue: 100 / 255, alpha: 1) | |
static let carbsColor = UIColor(red: 99 / 255, green: 218 / 255, blue: 56 / 255, alpha: 1) | |
// Equivalent to carbsColor with alpha 0.14 on a black background | |
static let darkCarbsColor = UIColor(red: 0.07, green: 0.12, blue: 0.04, alpha: 1) | |
static let glucose = UIColor(red: 79 / 255, green: 173 / 255, blue: 248 / 255, alpha: 1) | |
// Equivalent to glucoseColor with alpha 0.14 on a black background | |
static let darkGlucose = UIColor(red: 0.02, green: 0.10, blue: 0.14, alpha: 1) | |
static let workoutColor = glucose | |
// Equivalent to workoutColor with alpha 0.14 on a black background | |
static let darkWorkoutColor = darkGlucose | |
static let disabledButtonColor = UIColor.gray | |
static let darkDisabledButtonColor = UIColor.disabledButtonColor.withAlphaComponent(0.14) | |
static let chartLabel = HIGWhiteColor() | |
static let chartNowLine = HIGWhiteColor().withAlphaComponent(0.2) | |
static let chartPlatter = HIGWhiteColorDark() | |
// MARK: - HIG colors | |
// See: https://developer.apple.com/watch/human-interface-guidelines/visual-design/#color | |
private static func HIGPinkColor() -> UIColor { | |
return UIColor(red: 250 / 255, green: 17 / 255, blue: 79 / 255, alpha: 1) | |
} | |
private static func HIGPinkColorDark() -> UIColor { | |
return HIGPinkColor().withAlphaComponent(0.17) | |
} | |
private static func HIGRedColor() -> UIColor { | |
return UIColor(red: 1, green: 59 / 255, blue: 48 / 255, alpha: 1) | |
} | |
private static func HIGRedColorDark() -> UIColor { | |
return HIGRedColor().withAlphaComponent(0.17) | |
} | |
private static func HIGOrangeColor() -> UIColor { | |
return UIColor(red: 1, green: 149 / 255, blue: 0, alpha: 1) | |
} | |
private static func HIGOrangeColorDark() -> UIColor { | |
return HIGOrangeColor().withAlphaComponent(0.15) | |
} | |
private static func HIGYellowColor() -> UIColor { | |
return UIColor(red: 1, green: 230 / 255, blue: 32 / 255, alpha: 1) | |
} | |
private static func HIGYellowColorDark() -> UIColor { | |
return HIGYellowColor().withAlphaComponent(0.14) | |
} | |
private static func HIGGreenColor() -> UIColor { | |
return UIColor(red: 4 / 255, green: 222 / 255, blue: 113 / 255, alpha: 1) | |
} | |
private static func HIGGreenColorDark() -> UIColor { | |
return HIGGreenColor().withAlphaComponent(0.14) | |
} | |
private static func HIGWhiteColor() -> UIColor { | |
return UIColor(red: 242 / 255, green: 244 / 255, blue: 1, alpha: 1) | |
} | |
private static func HIGWhiteColorDark() -> UIColor { | |
// Equivalent to HIGWhiteColor().withAlphaComponent(0.14) on black | |
return UIColor(red: 33 / 255, green: 34 / 255, blue: 35 / 255, alpha: 1) | |
} | |
} | |
// Extension to add colors with alpha channels, from https://crunchybagel.com/blend-uicolor-swift-extension/ | |
extension UIColor { | |
func add(overlay: UIColor) -> UIColor { | |
var bgR: CGFloat = 0 | |
var bgG: CGFloat = 0 | |
var bgB: CGFloat = 0 | |
var bgA: CGFloat = 0 | |
var fgR: CGFloat = 0 | |
var fgG: CGFloat = 0 | |
var fgB: CGFloat = 0 | |
var fgA: CGFloat = 0 | |
self.getRed(&bgR, green: &bgG, blue: &bgB, alpha: &bgA) | |
overlay.getRed(&fgR, green: &fgG, blue: &fgB, alpha: &fgA) | |
let r = fgA * fgR + (1 - fgA) * bgR | |
let g = fgA * fgG + (1 - fgA) * bgG | |
let b = fgA * fgB + (1 - fgA) * bgB | |
return UIColor(red: r, green: g, blue: b, alpha: 1.0) | |
} | |
static func +(lhs: UIColor, rhs: UIColor) -> UIColor { | |
return lhs.add(overlay: rhs) | |
} | |
} | |
var backgroundColor = UIColor.chartPlatter | |
var overlayColor = UIColor.glucose | |
//backgroundColor = UIColor.white | |
print("Contrast ratios for UIColor.glucose with varying alpha on UIColor.chartPlatter background.") | |
for alpha in [0.2, 0.3, 0.4, 0.5, 0.6] { | |
let foregroundColor = backgroundColor + overlayColor.withAlphaComponent(CGFloat(alpha)) | |
print(alpha, foregroundColor.contrastRatio(to: backgroundColor), foregroundColor.sufficientContrast(to: backgroundColor)) | |
} | |
// The range color I've been using in the Watch app, at alphas of 0.6 (active) and 0.4 (overridden): | |
let rangeColor = UIColor(red: 158/255, green: 215/255, blue: 245/255, alpha: 1) | |
overlayColor = rangeColor | |
print("\nContrast ratios for the range color I used, with varying alpha on UIColor.chartPlatter background.\n") | |
for alpha in [0.4, 0.5, 0.6] { | |
let foregroundColor = backgroundColor + overlayColor.withAlphaComponent(CGFloat(alpha)) | |
print(alpha, foregroundColor.contrastRatio(to: backgroundColor), foregroundColor.sufficientContrast(to: backgroundColor)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment