色相環って知っていますか?
いわゆる色相環
カラーピッカーとかでよく見かけるこういうのですね。
via 色相 - Wikipedia
マンセルの色相環
ただ、僕が言ってる色相環はこっちのこと。
マンセル表色系 1 が提唱している 色相の連続的な変化を順序立てて円環にして並べたもの を指しています。
PCCS の色相環
更に PCCS(Practical Color Co-ordinate System:日本色研配色体系)によって作られた色相環もあります。
向かい合う色が心理補色 2 になるものでこんな感じのものです。
今回はこの PCCS の色相環の12色に簡略化されたものを作っていきたいと思います!
via PCCS(Practical Color Co-ordinate System:日本色研配色体系)
作ってみよう!
ってどうやって作ろう?
色々と考えました。
- CSS でがんばる とか
- 正十二角形の辺を太くして色変えて丸める とか
もう画像でいいじゃん
ふたつ目の案が良さそうだと思いましたが、正十二角形を描画するのどうするの?
canvas
でやってみるか!となったわけです
canvas で実装
HTML
<canvas id="hue-circle"></canvas>
これだけ。
CSS
なし(canvas は CSS で高さとか色とか指定できない)。
JS
大半は JS で実装します。
1. canvas 要素を取得して高さとか決める
const canvas = document.getElementById('hue-circle');
canvas.width = '300px';
canvas.height = '300px';
2. 描画できるように2Dコンテキストを取得する
const ctx = canvas.getContext('2d');
3. 円弧を描いてみる
canvas の円弧を描く基本はこんな感じです。
/**
* 円弧の描画
* @param {Object} ctx - 描画用 2D コンテキスト
* @param {number} x - 円弧の中心の X 座標
* @param {number} y - 円弧の中心の Y 座標
* @param {number} radius - 円弧の半径
* @param {number} startAngle - 円弧の開始角度
* @param {number} endAngle - 円弧の終了角度
* @param {string} colorCode - (任意)円弧の塗りつぶしカラーコード
*/
function fill(ctx, x, y, radius, startAngle, endAngle, colorCode) {
// 描画用にパスを作成
ctx.beginPath();
// "注記"参照
ctx.moveTo(x, y);
// 開始角度~終了角度の円弧描画をパスに登録(toRadianメソッドはラジアン角へ変換している)
ctx.arc(x, y, radius, toRadian(startAngle), toRadian(endAngle));
// 塗りつぶしの色を登録
ctx.fillStyle = colorCode;
// パスの内部エリアを塗りつぶして、単色の図形を描く
ctx.fill();
}
moveTo
については次のような 注記 が有りました。
注記:
beginPath()
を呼び出した直後や canvas を新規作成した直後など、現在のパスが空であるときに最初にパスを構築するコマンドは、実際は何であるかにかかわらず常にmoveTo()
として扱われます。このためパスをリセットした後はほぼ必ず、開始位置を明示することが必要になるでしょう。
via canvas に図形を描く - MDN web docs
今回は塗りつぶしだけど、縁取りする図形を描画する場合は stroke
でいけます。
4. 12色の円弧を描いてみる
先程の fill
関数を12回呼び出すことで実現しています。
// 黄色始まりのカラーコード一式(vivid トーン)
const colors = Object.values({
'Y' : '#FFE600',
'YG': '#99CF15',
'G' : '#33A23D',
'GB': '#008678',
'gB': '#055D87',
'B' : '#0F218B',
'V' : '#281285',
'P' : '#56007D',
'RP': '#AF0065',
'R' : '#EE0026',
'rO': '#FE4118',
'yO': '#FF7F00'
});
// 円弧の最も高い位置 270° から 15° 引いた角度から描画をはじめる
let angle = 255
// 12 回ループ
for (let i = 0; i < 12; i++) {
// 30° 分を描画する
fill(ctx, x, y, radius, angle, angle + 30, colors[i]);
// 次回描画用に 30° 加算する
angle += 30;
}
黄色の円弧の中心を一番上にしたいために 255° という中途半端な角度から開始しています。
270 - (30 / 2)
ってことですね。
5. 真ん中を白い円でくり抜こう
くり抜くというか、白い小さな円弧を上から描画しているだけです。
fill(ctx, x, y, radius / 2, 0, 360, '#FFFFFF');
半径を 1 / 2
して 360° まるっと描画しています。
色相環出来ました!
CodePen にUPしてみました!
描画の様子がわかりやすいように、1色ずつ止めながら描画させています。
See the Pen HueCircle by あずきしろもち (@azukisiromochi) on CodePen.
おわりに
canvas
を直接利用したのは初めてでしたが、なんとか出来ました。
座標を扱うので少しとっつきにくい感じはしますが、慣れれば便利なのかな~
ちなみに arc
関数使っているところを lineTo
関数に変えてやれば正多角形が作れたりもします。
(座標計算がそれこそしんどいけど)
こんどは CSS で作ってみようかな!