LoginSignup
4
2

More than 5 years have passed since last update.

[try! Swift Tokyo 2019] Liz Marleyさんの「アクセシビリティのためのカラーコントラスト」をリスペクトする

Posted at

try! Swift Tokyo 2019

初日を終えて、楽しかったです!
個人的に一番刺さったセッションが、Liz Marletさんの「アクセシビリティのためのカラーコントラスト」(PDF)でした。
というのも、個人でリリースしているアプリの中にただカラーコードを表示させるだけのものがあり、暇な移動時間に作ってリリースして以来完全に放置していたので、これにコントラスト比が表示される機能を足したら良いんじゃない?
と思ったからです。

License

とはいえ、勝手にコードをコピペ実装するのはダメ、絶対!
ということでセッション終了後通路にいたLizさんを捕まえて拙い英語で「May I use your code in my app?」って聞いてみました。
心優しいLizさんは快諾いただき、使う前にコードをチェックした方が良いかも、というアドバイスまでいただけました。
それはもう女神でした。

という事で実装

ここは胸を張ってLizさんのコードをコピペします。
だって、いいって言ったんだもん!

func relativeLuminance(_ color: CGColor) -> CGFloat {
    let sRGBColorSpace = CGColorSpaceMakeSRGB // ???
    let sRGB = color.converted(to: sRGBColorSpace,
                               intent: .defaultIntent,
                               options: nil)!.components!
    let adjusted = sRGB.map { (c) -> CGFloat in
        if c <= 0.03928 { return c / 12.92
        } else { return pow((c + 0.055)/1.055, 2.4) }
    }
    return 0.2126 * adjusted[0] +
           0.7152 * adjusted[1] +
           0.0722 * adjusted[2]
}

func contrastRatio(_ foreground: CGColor, _ background: CGColor) -> CGFloat {
     let ratio = (foreground + 0.05) / (background + 0.05)
     return ratio > 1 ? ratio : 1 / ratio
}

そしてビルド! からのコンパイルエラー!!
スクリーンショット 2019-03-22 0.59.05.png

そうですよね、コピペで新機能が実装できるなんてそんなうまい話ないですよね。
という事で誠に僭越ながら、手元環境でコンパイルできるように少し書き換えさせていただき、勝手なワガママで最後のratioが小数点第二位で丸められるようにしました。

func relativeLuminance(_ color: CGColor) -> CGFloat {
    let sRGBColorSpace = CGColorSpace(name: CGColorSpace.extendedSRGB)!
    let sRGB = color.converted(to: sRGBColorSpace,
                               intent: .defaultIntent,
                               options: nil)!.components!
    let adjusted = sRGB.map { (c) -> CGFloat in
        if c <= 0.03928 { return c / 12.92
        } else { return pow((c + 0.055)/1.055, 2.4) }
    }
    return 0.2126 * adjusted[0] +
        0.7152 * adjusted[1] +
        0.0722 * adjusted[2]
}

func contrastRatio(_ foreground: CGColor, _ background: CGColor) -> CGFloat {
    let ratio = (relativeLuminance(foreground) + 0.05) / (relativeLuminance(background) + 0.05)
    let result = ratio > 1 ? ratio : 1 / ratio
    return round(result * 100) / 100
}

これで無事手元環境でビルドすることができました。
最後にLizさんのアドバイスに忠実に従い、テストを少々。。。

    func testContrastRatioWhite() {
        let vc = ViewController()
        let color1 = UIColor.white.cgColor
        let color2 = UIColor.black.cgColor
        let ratio = vc.contrastRatio(color1, color2)

        XCTAssertEqual(ratio, 21.0)
    }

    func testContrastRatioBlue() {
        let vc = ViewController()
        let color1 = UIColor.black.cgColor
        let color2 = UIColor.blue.cgColor
        let ratio = vc.contrastRatio(color1, color2)

        XCTAssertEqual(ratio, 2.44)
    }

    func testContrastRatioRed() {
        let vc = ViewController()
        let color1 = UIColor.red.cgColor
        let color2 = UIColor.black.cgColor
        let ratio = vc.contrastRatio(color1, color2)

        XCTAssertEqual(ratio, 5.25)
    }

    func testContrastRatioGreen() {
        let vc = ViewController()
        let color1 = UIColor.black.cgColor
        let color2 = UIColor.green.cgColor
        let ratio = vc.contrastRatio(color1, color2)

        XCTAssertEqual(ratio, 15.30)
    }

    func testContrastRatioBlack() {
        let vc = ViewController()
        let color1 = UIColor.black.cgColor
        let color2 = UIColor.black.cgColor
        let ratio = vc.contrastRatio(color1, color2)

        XCTAssertEqual(ratio, 1.0)
    }

テストで比較する値はLizさんオススメのこちらで取得させていただきました。

テストを実行して、、、
スクリーンショット 2019-03-22 1.11.22.png
良きですね。

これで新機能のリリースは目前です!
というわけで、

Lizさん本当に素晴らしいセッションをありがとうございました!

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2