Skip to content

Instantly share code, notes, and snippets.

@elnjensen
Created October 13, 2018 02:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elnjensen/e7b649e83b6213f9fbe8e503d59f98a8 to your computer and use it in GitHub Desktop.
Save elnjensen/e7b649e83b6213f9fbe8e503d59f98a8 to your computer and use it in GitHub Desktop.
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