Help us understand the problem. What is going on with this article?

canvas で色相環を作ってみた

More than 1 year has passed since last update.

色相環って知っていますか?

いわゆる色相環

カラーピッカーとかでよく見かけるこういうのですね。

色相環

via 色相 - Wikipedia

マンセルの色相環

ただ、僕が言ってる色相環はこっちのこと。

マンセルの色相環
マンセル表色系 1 が提唱している 色相の連続的な変化を順序立てて円環にして並べたもの を指しています。

via マンセル・カラー・システム - Wikipedia

PCCS の色相環

更に PCCS(Practical Color Co-ordinate System:日本色研配色体系)によって作られた色相環もあります。
向かい合う色が心理補色 2 になるものでこんな感じのものです。

pccs-hue.png

今回はこの PCCS の色相環の12色に簡略化されたものを作っていきたいと思います!

via PCCS(Practical Color Co-ordinate System:日本色研配色体系)

作ってみよう!

ってどうやって作ろう?

色々と考えました。

  • CSS でがんばる とか
  • 正十二角形の辺を太くして色変えて丸める とか
  • もう画像でいいじゃん

ふたつ目の案が良さそうだと思いましたが、正十二角形を描画するのどうするの?

canvas でやってみるか!となったわけです :yum:

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 :pencil2: にUPしてみました!

描画の様子がわかりやすいように、1色ずつ止めながら描画させています。

See the Pen HueCircle by あずきしろもち (@azukisiromochi) on CodePen.

おわりに

canvas を直接利用したのは初めてでしたが、なんとか出来ました。

座標を扱うので少しとっつきにくい感じはしますが、慣れれば便利なのかな~ :thinking::question:

ちなみに arc 関数使っているところを lineTo 関数に変えてやれば正多角形が作れたりもします。

座標計算がそれこそしんどいけど

こんどは CSS で作ってみようかな! :yum:


  1. マンセル・カラー・システム (Munsell color system) とは、色を定量的に表す体系である表色系の1つ。色彩を色の三属性(色相、明度、彩度)によって表現する。マンセル表色系、マンセル色体系、マンセル システムとも言う。 

  2. ある色の残像として現われる色をその色の心理補色(または生理補色)と呼ぶ。例えば赤をしばらく見たあとに、白紙に目を移すと見える青緑が該当する。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした