Chapter 05

色の指定

miku
miku
2021.11.10に更新

色の名前による指定

fill("orange");

CSSではウェブカラーという仕組みがあり、色名による色の指定を行うことができるが、p5.jsでもウェブカラーの互換性があり、fill()stroke() に色名を指定することができる。

一般的によく使用される色の名前の英語表記はたいてい使用ができる。たとえば white, black, gray, red, green, blue, pink, purple, brown, yellow, orange ...など。

他にも多数の色名が指定できるので、詳細はウェブカラーの色名一覧が掲載されている外部サイトを参考にしてほしい。

https://www.w3schools.com/colors/colors_names.asp

指定した色名は小文字に変換されるので、大文字小文字を区別して指定する必要はない。たとえば OrAnGe と指定すると、内部では orange として扱われる。

数値による指定

色名による指定は便利だが、用意された名前以外の色を指定できないことや、なにかの計算によってできた数値を色にしたい場合もあるので、数値による色の指定方法も抑えておく必要がある。

グレースケール

fill(100);

fill()stroke() に、1つの数値を指定するとグレースケールの色番号を指定したと認識される。指定した数値が 0 なら黒、255 なら白、それ以外は灰色になる。

stroke(-100); // stroke(0) として扱われる
fill(1000); // fill(255) として扱われる

もし範囲外の数値を指定した場合、0 未満なら 0255 以上なら 255 として補正される。

RGB

複数の色を混ぜて新たな色を表現する方法の一つにRGBというものがある。混ぜると言っても絵の具のようなものではなく、発光による色の混ぜ方だ。

混ぜるということは少なくとも2色は必要だが、発光による色の混ぜ方では、2色ではどう混合しても作れない色がでてくる。例えば赤と緑からは青色そのものや青色が混じった色をつくることができない。同じように赤を緑と青で、緑を赤と青から作ることができないが、この3つの色を組み合わせれば、ほとんどの色を作ることができるので、赤・緑・青の色の強弱で色を表現したい。この3色を原色と呼び、英語表記だと Red, Green, Blue なので、頭文字を合わせてRGBと呼ぶ。

RGBそれぞれの色の強弱の度合いだが、一般的なディスプレイでは赤・緑・青それぞれが256色使用できるので、それの組み合わせ数である 256 * 256 * 256 = 16777216 もの色を表現することが可能である。このことに合わせてp5.jsでも色の指定範囲が256色になっている。

fill(255, 128, 64); // 赤, 緑, 青

3つの数値を指定すると、RGBの順番で色を指定したと認識される。数値の範囲はそれぞれ 0~255 である。

stroke(500, 100, 200); // stroke(255, 100, 200) として扱われる
fill(-100, 128, -200); // fill(0, 128, 0) として扱われる

もし範囲外の数値を指定した場合、0 未満なら 0255 以上なら 255 として補正される。

色を1つの値で表現する

const r = 218;
const g = 63;
const b = 5;

RGBを変数や定数に格納しようとすると、赤・緑・青の3つ分必要になる。1つの色を表現するのに3つの変数を用意するのは面倒なので、できるなら1つの値で表したい。

// R = 218, G = 63, B = 5 を結合した表現
const rgb = 218063005;

たとえばだが、RGBの値を結合した数を作るという方法があるだろう。桁を揃えないと切れ目が分からなくなるので、必ず3桁になるように先頭に0を付けることを考慮すると、9桁の1つの数ができる。この数からRGBを取り出すときは、3桁ごとにうまく切り出せばいい。

これでも表現できなくはないのだが、16進数という数の表現を利用すると更に扱いやすくなる。

普段我々が使用している数字は10進数と呼ばれているもので、0~9の10種類の数字で数を表現する。これに対して、16進数では名前の通り16種類の数字で数を表現する。ただし数字は0~9の10種類しかないので、アルファベットのA~Fを使用して残りの数字を表現する。具体的には下記のとおりだ。

10進数 16進数
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 A
11 B
12 C
13 D
14 E
15 F

10進数は1桁で10種類の数を扱うことができ、2桁で0~99の100種類になる。それに対して、16進数は1桁で16種類、2桁で0~FFの256種類になる。

16進数2桁で表現できる数が256種類というのは、RGBそれぞれの色数と一致しているので都合がよい。16進数は言語単位でサポートされている場合が多く、JavaScriptもそのうちの1つである。

console.log(0xa); // 10
console.log(10 === 0xa); // true

JavaScriptでは、記述した数が16進数であることを明示するために数の前に 0x を付ける。A~Fの文字は大文字小文字どちらを使用してもよい。

// r = 0xda
// g = 0x3f
// b = 0x5

// 16進数
const rgb = 0xda3f05;

先ほどと同じようにRGBそれぞれの値を16進数でくっつけた形にする。最大値は0xFFと2桁なので、一桁の数には先頭に0を付けて必ず2桁になるようにすると、16進数6桁の数が出来上がる。

p5.jsでは16進数によるRGBの指定に対応しているのだが、実はこの表記での指定はうまくいかない。

fill(0x123456);

たとえば fill() に16進数の色を指定しても、これが16進数表記で指定されたことはコードを書いた本人だけが分かることで、JavaScriptの機能として、渡された数値が16進数表記であるかどうかを判定する機能がない。なので 0x123456 はグレースケールの指定だとp5.js側は認識するだろう。

これの解決方法として文字列で16進数の色を指定する必要がある。

fill("#123456");

文字列で16進数を指定するには、0x の代わりに # を付けて、その後に16進数の数を記述する。これはJavaScriptの機能ではなく、p5.jsでは16進数での色の指定を認識するために、こういう形式で指定する必要があるということだ。

p5.jsに限らず、色を文字列で指定するライブラリは多い。数が16進数表記だということをライブラリ側からだと認識できないのと、数には扱える最大値があり、16進数6桁程度だと問題は無いが、これに別の情報、たとえば透明度などの情報を更に加える場合もあり、それだと扱える数の最大値を超えてしまう可能性がある。なので文字列として扱ったほうが便利なわけだ。

fill(255, 0, 255); // 10進数でのRGBの指定
fill("#ff00ff"); // 16進数でのRGBの指定

まとめると、RGBの指定方法は、10進数あるいは文字列での16進数の形式で渡す必要がある。

HSB

RGBでの色の指定ができるようになったが、RGBの尺度で色を指定するのが難しいケースがある。

fill(random(255), random(255), random(255));

たとえば、色をランダムにしたいという場合、上記のように書いてしまうと、本当にあらゆる色が作られる可能性があるが、明るい色だけが出てほしい、白や黒のような色味のない色は出てこないでほしい、暖色だけを取り出したい、などのケースがある。

これらの要望をRGBで指定するのは難しいので、代わりにHSBという色の体系を利用したい。

RGBそれぞれの値を3次元の座標だと考えて色を配置すると立方体の形になる。

ここで白の点を視点の真正面に来るようにして、更にその裏に黒の点が来るように、つまり白の点で黒の点が見えなくなるように回転させる。

そうすると白を中心とした六角形に見えるだろう。これを更に円になるように変形した後、0度の方向に赤色が来るように回転させる。

これまでの操作で作られた形がHSBという名前の色の体系になる。

円周を赤から時計回りに見ていくと、赤、オレンジ、黄色、緑...と色が変化しているだろう。これら一つ一つの色を色相と呼ぶ。円周を回ることで色相が変化しているのだから、円の中心からみた角度で色相を指定することができる。

円の中央に近づくほど白色になり、逆に離れるほど色味が付いた色に見えるだろう。これが彩度と呼ばれるもので、円の中央からの距離で決まる。

上記画像の円が実は円柱を真上から見たもので、奥行きがあるものだと考える。奥にいくほど円全体の色を暗くすると、明るさの表現をすることができるだろう。これが明度と呼ばれるもので、円柱の奥からの距離で決まる。

HSBは色相・彩度・明度によって色を表現するものになる。色相・彩度・明度の英語表記は Hue, Saturation, Brightness なので、頭文字を繋げてHSBと呼ぶ。明度を Value の表記にしてHSVと呼ばれることも多いが、p5.jsではHSBとして扱うので、この本でも一貫してHSBと呼ぶことにしたい。

colorMode(HSB);
fill(360, 100, 100); // 色相, 彩度, 明度

fill()stroke() に3つの数値を指定するとRGBだと認識されるので、前もって colorMode(HSB) で、色の扱いがHSBになるように切り替えておく。

色相は角度なので指定できる数値の範囲は 0~359 になる。彩度と明度は割合(パーセンテージ)なので、0~100 の範囲で数値を指定する。

colorMode(HSB);

stroke(360, 50, 80); // stroke(0, 50, 80) として扱われる
fill(-100, 200, -100); // fill(0, 100, 0) として扱われる

色相は角度なのだが、0 未満あるいは 360 以上の指定は 0 として扱われる。もし角度の数値を色相として表現する場合は、0~360の範囲になるように前もって補正しておく必要がある。

彩度・明度は 0 未満なら 0100 以上なら 100 として補正される。

透明度

// グレースケール(255)と透明度(128)
fill(255, 100);

// RGB(255, 0, 0)と透明度(128)
fill(255, 0, 0, 128);

colorMode(HSB);

// HSB(100, 100, 100)と透明度(0.5)
fill(100, 100, 100, 0.5);

色の指定の後に更に数値を指定すると、その数値は透明度の指定だと認識される。透明度は0に近づくほど色が透明になり、逆に最大値に近づくほど不透明になる。

グレースケール・RGBでの透明度の範囲は 0~255 だが、HSBは 0~1 になる。

// エラー
fill("#ffffff", 100);

// OK - fill(255, 100); と同様の指定
fill("#ffffff64");

16進数文字列に透明度を指定する場合は、透明度を16進数に直したものを後ろにくっつけるようにする。

最大値の変更

// RGB+透明度の最大値が(100, 100, 100)になる
colorMode(RGB, 100);

// RGBの最大値が(10, 20, 30)になる
colorMode(RGB, 10, 20, 30);

// HSB+透明度の最大値が(10, 20, 30, 40)になる
colorMode(HSB, 10, 20, 30, 40);

colorMode() には RGBHSB のような色の体系を指定することができるが、その後に数値を指定することで色の最大値の変更をすることができる。

たとえば、HSBの透明度の範囲だけ 0~1 なのが気に食わない場合は colorMode(HSB, 360, 100, 100, 100) のように修正できる。他にも colorMode(RGB, 1)colorMode(RGB, 100) と記述すると、割合(パーセンテージ)の指定に変えることができる。

colorMode(RGB, 100);
fill(50); // もともとのfill(128)と同じ色になる

colorMode(RGB, n) あるいは colorMode(HSB, n) の指定は、グレースケールの範囲も影響を受ける。

実数での指定

fill(100.4); // グレー(100)
fill(100.5); // グレー(101)

fill(100.4, 100.4, 100.4); // RGB(100, 100, 100)
fill(100.5, 100.5, 100.5); // RGB(101, 101, 101)

指定した色の値は全て四捨五入される。

color()

const c = color(255, 0, 0); // RGB(255, 0, 0)として認識される
stroke(c);
fill(c);

color() に色を指定すると、色の値をラップしたColorオブジェクトが返される。このオブジェクトは stroke()fill() に指定することができる。

配列

stroke([255, 255, 255]); // RGBを配列で指定する
fill([255, 0, 0, 80]); // RGB+透明度を配列で指定する

stroke()fill() は配列での色指定にも対応している。

色の取り出し

const c = color(255, 0, 0);
red(c); // 赤
green(c); // 緑
blue(c); // 青
alpha(c); // 透明度
hue(c); // 色相
saturation(c); // 彩度
brightness(c); // 明度

red("orange"); // ウェブカラー文字列からの色の取り出し
red("#ff0000"); // 16進数文字列からの色の取り出し
red([255, 0, 0]); // 配列からの色の取り出し

Colorオブジェクト、文字列、配列などに入った色から、個別の色の値を取り出すことができる。

色の指定を利用した作例

function setup() {
  createCanvas(windowWidth, windowHeight);
  colorMode(HSB, width, 100, 100);
}

function draw() {
  fill(mouseX, 100, 100);
  circle(mouseX, mouseY, 100);
}

マウス座標に円を描き、マウスのx座標をそのまま色相にしたものを塗りとして適用した作例。

色相の範囲は 0~359 だが、これを 0~width に変更すれば、画面横幅いっぱいに色を分散できる。