How to compute color contrast ratio between two UIColor instances

后端 未结 2 2141
青春惊慌失措
青春惊慌失措 2021-02-15 17:35

I\'m looking for a concise way to compute the color contrast ratio between two UIColor instances in Swift. I\'ve found examples that are close but are overly compli

相关标签:
2条回答
  • 2021-02-15 18:20

    If building for WatchOS where CoreImage is not available or for whatever reason you do not want to rely on CoreImage and therefore CIColor is unavailable, replace @Mobile Dan's luminance function with:

      private func luminance() -> CGFloat {
      // https://www.w3.org/TR/WCAG20-TECHS/G18.html#G18-tests
    
        func adjust(colorComponent: CGFloat) -> CGFloat {
          return (colorComponent < 0.03928) ? (colorComponent / 12.92) : pow((colorComponent + 0.055) / 1.055, 2.4)
        }
    
        var red: CGFloat = 0
        var green: CGFloat = 0
        var blue: CGFloat = 0
        var alpha: CGFloat = 0
        getRed(&red, green: &green, blue: &blue, alpha: &alpha)
    
        return 0.2126 * adjust(colorComponent: red)
          + 0.7152 * adjust(colorComponent: green)
          + 0.0722 * adjust(colorComponent: blue)
      }
    
    0 讨论(0)
  • 2021-02-15 18:29

    UIColor extension with contrast ratio and luminance

    The following UIColor extension includes a static and instance contrast ratio method. A bonus luminance method is included since it is used by the static contrastRatio(between:and:) method.

    import UIKit
    
    extension UIColor {
    
        static func contrastRatio(between color1: UIColor, and color2: UIColor) -> CGFloat {
            // https://www.w3.org/TR/WCAG20-TECHS/G18.html#G18-tests
    
            let luminance1 = color1.luminance()
            let luminance2 = color2.luminance()
    
            let luminanceDarker = min(luminance1, luminance2)
            let luminanceLighter = max(luminance1, luminance2)
    
            return (luminanceLighter + 0.05) / (luminanceDarker + 0.05)
        }
    
        func contrastRatio(with color: UIColor) -> CGFloat {
            return UIColor.contrastRatio(between: self, and: color)
        }
    
        func luminance() -> CGFloat {
            // https://www.w3.org/TR/WCAG20-TECHS/G18.html#G18-tests
    
            let ciColor = CIColor(color: self)
    
            func adjust(colorComponent: CGFloat) -> CGFloat {
                return (colorComponent < 0.04045) ? (colorComponent / 12.92) : pow((colorComponent + 0.055) / 1.055, 2.4)
            }
    
            return 0.2126 * adjust(colorComponent: ciColor.red) + 0.7152 * adjust(colorComponent: ciColor.green) + 0.0722 * adjust(colorComponent: ciColor.blue)
        }
    }
    

    Example Use

    // static method
    let contrastRatio1 = UIColor.contrastRatio(between: UIColor.black, and: UIColor.white)
    print(contrastRatio1) // 21.0
    
    // instance method
    let contrastRatio2 = UIColor.black.contrastRatio(with: UIColor.white)
    print(contrastRatio2) // 21.0
    

    Note

    Following these links: https://www.w3.org/TR/css-color-4/#predefined https://github.com/dequelabs/axe-core/issues/1629#issuecomment-509880306

    For predefinite colorspace (like in iOS see this https://developer.apple.com/videos/play/wwdc2016/712/) and also in general the correct THRESHOLD value is 0.04045 and not 0.03928.

    0 讨论(0)
提交回复
热议问题