color-thiefで画像に応じて背景色を動的に変える
はじめに
画像に応じて背景色(css による background-color 等)を動的に変える実装をしました。
今ある画像だけでいい感じに一覧表示したい
以下のような透過画像を表示する場合、背景色によっては見づらくなってしまいます。
特に画像を一覧表示する場合、様々な色合いの画像が存在するので、背景色を一意に定めるだけでは不十分です。
画像を一覧表示のサムネイル画像を用意する手段もありますが、既存の画像のサムネイル画像を作る作業が必要になります。
そこで、今回はcolor-thief-reactで画像の色を取得し、背景色を動的に変える実装をしました。
今回行った実装
- color-thief-reactで画像からDominatColorを取得
- dominant colorを元に、適した背景色を決定する
- 明度が高ければ、背景色をグレーにする
- 明度が低ければ、背景色を白にする
コード
主要なコードは以下の通りです
背景色を変える
color-thiefは以下のような使い方をします。dataには画像で一番使われている色(Dominant Color)が保存されます。
<Color src={IMAGE_URL}>
{({ data, loading, error }) => (
<div style={{ color: data }}>
Text with the predominant color
</div>
)}
</Color>
以下のようにして、画像の背景色が変わるようにします。
<Color src={props.imgSrc} format="rgbArray">
{({ data }) => {
//dominant colorから背景色を決定する
const bgColor = getBgColor(data)
return(
<div>
<img src={props.imgSrc} style={{ backgroundColor: bgColor }}/>
<div>dominant color: {data?.map((value: any) => <span>{value} </span>)}</div>
</div>
)
}}
</Color>
getBgColor
dominant colorの明度が高いか、低いかで背景色を決定します。
白のみの画像では、dominant colorが取得できず、undefined
になるので注意が必要です。
const getBgColor = ( rgb: ArrayRGB | undefined ) => {
if ( rgb !== undefined ) {
//明度が高い画像の背景色はgray
//明度が低い画像の背景色はwhite
return isLight( rgb ) ? 'gray' : 'white'
} else {
//白のみの画像の場合は背景色をgrayにする
return 'gray'
}
}
isLight
const isLight = ( rgb: ArrayRGB ) => {
const [r, g, b] = rgb.map(( value: any ) => value )
//130は自分で決めた値
if (( r * 299 + g * 587 + b * 114 ) / 1000 >= 130 ){
return true
}
return false
}
背景色から適した文字色が白か黒か判定する方法を応用して、明度が高いか、低いかを決定します。今回の場合は
( r * 299 + g * 587 + b * 114 ) / 1000 >= 130
と書かれている通り、左辺の値が130以上だったら、明度が高いとして、trueを返します(=背景色はグレー)。
実装後で比較
-
背景色を白色に固定
-
背景色をグレーに固定
-
今回の実装:背景色を動的に変える
画像によって、背景色が変わっており、画像が見やすくなりました。
おわりに
画像の色に応じて、背景色を変えるという手法について書いてみました。
color-thiefには画像からカラーパレットを作成できるので、アカウントのプロフィール画像でWebサイトのテーマが変わるといった実装もできそうですね。
おまけ:他に試した実装方法
背景色を動的に変えるために、試した手法を書いておきます。
canvasで1pxの画像で貼り付け、色を取得
- canvasで画像を読み込み、縦横1pxのサイズで貼り付ける
- 貼り付けた1pxの画像の色を取得する
透過されている部分が多いと、取得した色が透明rgba(0,0,0,0)
になりました。今回はアルファ値のない色が欲しかったので、こちらの実装は見送りました。
vibrant.jsで色を取得
color-thiefのように画像からカラーパレットを生成してくれるライブラリです。
Extract prominent colors from an image.
とあるように、画像で一番使われている色ではなく、目立った色を取得します。そのため、主要な色から明度を判定をするには不向きでした。
Discussion