はじめに
この記事は、JavaScript Advent Calendar 2022 の 20日目の記事です。
内容は、過去に以下の記事でも扱った chroma.js の話です。
●chroma.js を使った HSB(HSV) と16進数カラーコードの変換やその他の処理を p5.js Web Editor上で試す - Qiita
https://qiita.com/youtoy/items/513009ebfdd04872e059
もう少し補足すると、以下の記事に出てくる chroma.js での複数の色を使ったカラースケールの話と、p5.js でカラーパレットを使う話とを組み合わせた内容になります。
●Mastering Multi-hued Color Scales with Chroma.js
https://www.vis4.net/blog/2013/09/mastering-multi-hued-color-scales/
複数の色を使ったカラースケール
上で掲載していた「Mastering Multi-hued Color Scales with Chroma.js」という記事で、複数の色を使ったカラースケールの話について書かれています。
細かな話は省略しますが、その話の中で、複数の色を使ったカラースケールを改善するための方法について説明されています。
そして、chroma.js の「chroma.bezier()」や「chroma.scale() + scale.correctLightness()」を使った話が出てきていました。これらを使うと、複数の色を使ったスケールの結果を、良い感じにできるようです。
※ 自分が色の理論にそこまで詳しくないので、ざっくりな内容しか把握できてないのですが...
その話が気になったので、具体的にどんな結果が得られるかを、普段よく使っている p5.js を使って確かめてみる、というのが、これ以降の内容です。
(そして、良い感じのカラーパレットが生成できたら、今後、活用していけそうかなという思いもあり...)
chroma.js関連の話
以下で、今回利用する chroma.js の機能の、公式情報を見ていきます。
chroma.scale()
指定した 2色以上の色で、カラースケールを作成できます。色指定をしない場合、デフォルトは白黒の 2色になるようです。
https://gka.github.io/chroma.js/#chroma-scale
scale.mode()
カラースケールのモードを切り替えるもので、デフォルトは RGB ですが、HSL など他のものに変更することができます。
https://gka.github.io/chroma.js/#scale-mode
scale.colors()
カラースケールから、数字指定で色を取り出すためのものです。
https://gka.github.io/chroma.js/#scale-colors
scale.correctLightness() と chroma.bezier()
上に掲載した記事で出てきた、複数の色のカラースケールを作成する際に、良い感じの出力を得るために用いられていたものです。
https://gka.github.io/chroma.js/#scale-correctlightness
https://gka.github.io/chroma.js/#chroma-bezier
生成した色を p5.js で描画してみる
ここから、chroma.js でカラースケールを生成し、そこから色を取り出してカラーパレットを作るというのをやってみます。さらに、そのカラーパレットを使った描画を、p5.js を用いて行います。
p5.js で得た出力
まずは、p5.js で得た出力を掲載してみます。
6パターンのカラーパレットがありますが、補足などを以下で書いていきます。
出力の全てに共通の内容: 元にした色と出力した色の数
カラースケールを作成する際、元になる色として指定した内容を、ソースコードベースで示します。以下のように、「白・黄色・青・黒」の 4色を、元になる色として指定しました。
const colorList = ["white", "yellow", "blue", "black"];
また、出力する色の数は 10色としました。
const outputColorNum = 10;
出力の上 2つ
chroma.scale().mode("rgb") で得た出力と、scale.correctLightness() を加えたものの 2つです。scale.correctLightness() を加えたことで、左半分の色の変化の段階が、はっきりした感じになりました。
chroma.scale(colorList).mode("rgb").colors(outputColorNum),
chroma.scale(colorList).mode("rgb").correctLightness().colors(outputColorNum),
出力の真ん中の 2つ
chroma.scale().mode("hsl") で得た出力と、scale.correctLightness() を加えたものの 2つです。上の事例とは異なり、scale.correctLightness() を加えたことで、左半分の出力がずいぶん異なるものになりました。
chroma.scale(colorList).mode("hsl").colors(outputColorNum),
chroma.scale(colorList).mode("hsl").correctLightness().colors(outputColorNum),
出力の下 2つ
chroma.bezier().scale() で生成したカラースケールと、それに scale.correctLightness() を加えたものとなっています。左端から真ん中あたりの色が少し補正されているのが分かります。
chroma.bezier(colorList).scale().colors(outputColorNum),
chroma.bezier(colorList).scale().correctLightness().colors(outputColorNum),
ただ、他の事例と比べると、補正の影響が大きくはないようです。
このあたりは、元にする色の組み合わせなどで変わるのか、chroma.bezier().scale() を使うとこういった感じになるのか、そのあたりを判断するにはもう少しお試しをする必用がありそう...
p5.js Web Editor上での実装
最後に、上で掲載した出力を得るために、p5.js Web Editor上で作った内容を掲載します。CSS は特に変更してないため、HTML と JavaScript のファイルの内容のみ掲載します。
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.4.2/chroma.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css" />
<meta charset="utf-8" />
</head>
<body>
<main></main>
<script src="sketch.js"></script>
</body>
</html>
const outputColorNum = 10;
const colorList = ["white", "yellow", "blue", "black"];
const outputColorList = [
chroma.scale(colorList).mode("rgb").colors(outputColorNum),
chroma.scale(colorList).mode("rgb").correctLightness().colors(outputColorNum),
chroma.scale(colorList).mode("hsl").colors(outputColorNum),
chroma.scale(colorList).mode("hsl").correctLightness().colors(outputColorNum),
chroma.bezier(colorList).scale().colors(outputColorNum),
chroma.bezier(colorList).scale().correctLightness().colors(outputColorNum),
];
function setup() {
createCanvas(400, 350);
noStroke();
}
function draw() {
background(220);
const size = width / outputColorNum;
for (i = 0; i < outputColorList.length; i++) {
for (j = 0; j < outputColorNum; j++) {
fill(outputColorList[i][j]);
rect(
(j * width) / outputColorNum,
height * (0.05 + i * 0.16),
size,
size
);
}
}
}
あと上記を試した後に、「塗りつぶしの部分で透明度を設定する」というのもやってみました。
fill(outputColorList[i][j]);`
↓
`fill(`${outputColorList[i][j]}aa`);`