Last active
March 9, 2020 13:36
-
-
Save dnedrow/bc5b91b48d4f99d9fb7e48ccbfa2fed6 to your computer and use it in GitHub Desktop.
This protocol defines functions for determining contrasting colors and other color related values.
This file contains hidden or 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
| // Created by Nedrow, David E on 3/25/19. | |
| // Attribution 4.0 International (CC 4.0), see bottom. | |
| import UIKit | |
| // MARK: - UIColor+ContrastColor.swift | |
| /// This protocol defines functions for determining contrasting colors and other | |
| /// color related values. | |
| public protocol ContrastColorProtocol { | |
| /// Calculates the luminance of the given color. | |
| /// | |
| /// - Parameter color: The color for which the luminance is needed. | |
| /// - Returns: The luminance of the input color. If this could not be | |
| /// calculated, nil is returned. | |
| static func luminance(_ color: UIColor) -> Double? | |
| /// Returns a color that is a contrast to the given color. | |
| /// | |
| /// - Parameter color: The color for which a contrasting color is needed. | |
| /// - Returns: The contrasting color. | |
| static func contrastColor(_ color: UIColor) -> UIColor | |
| /// Indicates whether a light contrast color is needed for this color instance. | |
| /// | |
| /// - Returns: True if a light contrast color should be used with this color. | |
| /// `nil` is returned if the calculation failed. | |
| func useLightContrastingColor() -> Bool? | |
| } | |
| // MARK: - ContrastColorProtocol default implementation. | |
| /// Default implementations for static ContrastColorProtocol functions. | |
| public extension ContrastColorProtocol { | |
| /// Default implementation of luminance(_ color: UIColor) | |
| static func luminance(_ color: UIColor) -> Double? { | |
| // These weightings were proposed by StackOverflow user Gacek in post: | |
| // https://stackoverflow.com/a/1855903/1227012 | |
| let redWeight: CGFloat = 0.299 | |
| let greenWeight: CGFloat = 0.587 // The human eye favors the green spectrum. | |
| let blueWeight: CGFloat = 0.114 | |
| let alphaWeight: CGFloat = 0.0 // Alpha is deliberately ignored. | |
| var redValue: CGFloat = 0.0 | |
| var greenValue: CGFloat = 0.0 | |
| var blueValue: CGFloat = 0.0 | |
| var alphaValue: CGFloat = 0.0 | |
| if !color.getRed(&redValue, green: &greenValue, blue: &blueValue, alpha: &alphaValue) { | |
| return nil | |
| } | |
| return Double((redWeight * redValue) + (greenWeight * greenValue) + | |
| (blueWeight * blueValue) + (alphaWeight * alphaValue)) | |
| } | |
| /// Default implementation of contrastColor(_ color: UIColor) | |
| static func contrastColor(_ color: UIColor) -> UIColor { | |
| fatalError("contrastColor(_:) has not been implemented") | |
| } | |
| } | |
| // MARK: - ContrastColorProtocol instance methods. | |
| extension UIColor: ContrastColorProtocol { | |
| public func useLightContrastingColor() -> Bool? { | |
| guard let thisLuminance = UIColor.luminance(self) else { | |
| return nil | |
| } | |
| return !(thisLuminance >= 0.5) | |
| } | |
| } | |
| // This work is licensed under Attribution 4.0 International (CC 4.0) | |
| // You are free to: | |
| // Share — copy and redistribute the material in any medium or format | |
| // Adapt — remix, transform, and build upon the material | |
| // for any purpose, even commercially. | |
| // | |
| // This license is acceptable for Free Cultural Works. | |
| // The licensor cannot revoke these freedoms as long as you follow the license terms. | |
| // See https://creativecommons.org/licenses/by/4.0/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment