Flutter背景文字对比度计算

535 阅读2分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战」。

前言:

有个 Flutter 的项目,一些功能的文字的背景色是从数据库中取出来的,然后根据取出来的背景色,文字的颜色使用对比度友好的颜色(黑色或者白色)。

本来想偷偷懒,把其中的计算逻辑(商业机密)改改拿出来分享,结果发现自己简直就是坐井观天。

WCGA 有相关的计算公式:

G17: Ensuring that a contrast ratio of at least 7:1 exists between text (and images of text) and background behind the text | Techniques for WCAG 2.0 (w3.org)

还有设计师必备的理论:

设计师必修课:对比度、颜色的设计技巧解读 - 掘金 (juejin.cn)

也有 javascript 版的对比度计算:

文字背景对比度contrast ratio的计算公式 - 掘金 (juejin.cn)

天天写些后端业务代码,对 UI 比较钝感。好好学习,天天向上。

那写一个 Flutter(Dart) 版的吧。

参照上面的 WCAG 的计算公式和 javascript 版的写法,写了一版 Flutter(Dart) 的。

顺带写了一个 Demo,效果如下:

contrast_ratio.gif

背景文字对比度计算Flutter(Dart)版

  1. 先计算相对光线亮度(灰度)

    /// 计算相对光线亮度
    /// 公式: https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-procedure
    static num luminance(Color c) {
      List<num> rgb = [c.red, c.green, c.blue];
    
      List<num> lum = rgb
          .map((v) => () {
                num vs = v / 255;
                return (vs <= 0.03928)
                    ? vs / 12.92
                    : pow(((vs + 0.055) / 1.055), 2.4);
              }())
          .toList();
    
      return lum[0] * 0.2126 + lum[1] * 0.7152 + lum[2] * 0.0722;
    }
    
  2. 基于亮度计算对比度

    /// 计算对比度
    static num calcColorContrastRatio(Color color1, Color color2) {
      // 计算亮度
      num lum1 = luminance(color1);
      num lum2 = luminance(color2);
    
      // 稍亮颜色的亮度
      num lumLighter = max(lum1, lum2);
      // 稍暗颜色的亮度
      num lumDarker = min(lum1, lum2);
    
      // 对比度
      num ratio = (lumLighter + 0.05) / (lumDarker + 0.05);
      return ratio;
    }
    

    返回值类型直接用了 num,可以用 double。

对比度应用例

相关文章里说,WCAG 里的对比度标准分为3级:A标准、AA 标准、AAA 标准。

  • A 标准的对比度至少是 3 : 1。
  • AA 标准的对比度至少是 4.5 : 1。
  • AAA 标准的对比度至少是 7 : 1。

示例中使用了 AAA 标准。低于7时,文字使用白色;高于7时,文字使用黑色。

效果如上图:

相关代码:

helloflutter/hellodesign at main · bettersun/helloflutter (github.com)