要約
Flutterで画像上にバツボタンを配置する際、見やすさを向上させるユーティリティを作成しました。
補色やコントラスト比を自動計算し、WCAG基準に近い判定で最適な色を選択します。
はじめに
画像の上にバツボタン(閉じるボタン)を配置する際、背景によってボタンが見えづらくなることがあります。
この記事では、Flutterでコントラストを自動調整するユーティリティを実装した経緯と工夫点を紹介します。
対象読者
- UIのアクセシビリティに興味がある人
- Flutterで画像上にボタンを配置したい人
- コントラスト比や補色計算に関心がある人
内容
この記事では、画像上にバツボタンを配置する際の「見やすさ」「コントラスト」を自動調整するユーティリティの実装方法を解説します。
実装の背景
画像の色によっては、白や黒のバツボタンが見えづらくなることが多々あります。手動で色を調整するのは手間なので、色の補色やコントラスト比を自動計算し、最適な色を選ぶ仕組みを作りました。
実装コード
contrast_button_util.dart
の全体コード:
import 'dart:math';
import 'package:flutter/material.dart';
/// 画像上のバツボタンの見やすさ向上用ユーティリティ
class ContrastButtonUtil {
/// 補色を計算
static Color complementaryColor(Color color) {
return Color.fromARGB(
255,
255 - color.red,
255 - color.green,
255 - color.blue,
);
}
/// 補色と白・黒のコントラスト比を計算し、より高コントラストな色を返す(WCAG基準に近い判定)
static Color bestContrastColor(Color color) {
double luminance(Color c) {
double channel(int v) {
final d = v / 255.0;
return d <= 0.03928
? d / 12.92
: pow((d + 0.055) / 1.055, 2.4).toDouble();
}
return 0.2126 * channel(c.red) +
0.7152 * channel(c.green) +
0.0722 * channel(c.blue);
}
final l1 = luminance(color);
final lWhite = luminance(Colors.white);
final lBlack = luminance(Colors.black);
double contrast(double lA, double lB) => (lA + 0.05) / (lB + 0.05);
final contrastWhite =
l1 > lWhite ? contrast(l1, lWhite) : contrast(lWhite, l1);
final contrastBlack =
l1 > lBlack ? contrast(l1, lBlack) : contrast(lBlack, l1);
return contrastWhite > contrastBlack ? Colors.white : Colors.black;
}
/// バツボタン背景色(半透明円形)を返す
static Color backgroundForContrast(
Color? complementary, {
double opacity = 0.3,
}) {
if (complementary == null) return Colors.black.withValues();
final contrast = bestContrastColor(complementary);
return contrast == Colors.white
? Colors.black.withValues()
: Colors.white.withValues();
}
}
各メソッドの詳しい解説
complementaryColor
- 指定した色の補色(反対色)を計算します
- RGB各値を255から引くことで、色相が真逆になる色を算出しています
- 例:赤(255,0,0)の補色はシアン(0,255,255)になります
bestContrastColor
- 指定した色と「白」「黒」のコントラスト比を計算し、よりコントラストが高い方を返します
- コントラスト比はWCAG(Web Content Accessibility Guidelines)で推奨される計算式を参考にしています
-
luminance
関数で色の輝度を算出し、白・黒それぞれとのコントラスト比を比較します - これにより、背景色に対して最も見やすい色(白or黒)を自動で選択できます
backgroundForContrast
- バツボタンの背景色(半透明円形)を返します
- 補色(または指定色)に対して、最適なコントラスト色(白or黒)を選び、その色を半透明にして背景に使います
- 画像の上でも違和感なく、ボタンが目立つように工夫しています
この3つのメソッドを組み合わせることで、どんな画像の上でも
「見やすい❌ボタン」を自動生成できます。
コントラスト比の計算はWCAG基準に近いですが、完全準拠ではありません。必要に応じて調整してください。
工夫したポイント
- 補色計算で「色相が真逆」になるようにした
- コントラスト比を数値で比較し、白・黒のどちらが見やすいか自動判定
- 背景色も半透明で調整し、画像の上でも違和感なく表示
利用例
ご覧のように背景に応じて見やすい色が選択されます。
実際の実装はこのような形です。
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: ContrastButtonUtil.backgroundForContrast(
complementaryColor,
),
),
child: IconButton(
icon: const Icon(Icons.close, size: 32),
color: ContrastButtonUtil.bestContrastColor(
complementaryColor ?? Colors.black,
),
まとめ
Flutterで画像上にバツボタンを配置する際、コントラストを自動調整することでアクセシビリティと見やすさが向上します。ユーティリティ化することで、他のUIパーツにも応用可能です。