ここでは JavaScript の発展的な内容として、HTML の操作やグラフィックス関係のライブラリーについて説明する。
まずは HTML (CSS) での色の表現方法について説明し、その後、p5.js というグラフィックスを作成するための初心者向けの JavaScript のライブラリーを紹介する。さらに、一般的な HTML を操作するための JavaScript の関数についても説明する。
この資料のプログラム例では、手頃な例として色を扱うことが多いので、まず、最初に HTML (CSS) での色の表現方法について説明する。
CSS には "red", "blue" などの色名1で指定するほかに
RGB, HSL, OkLCh などの色の表現方法がある。
RGB は、色を赤(Red)、緑(Green)、青(Blue)の光の三原色の加算で表現する方法である。
CSS では rgb(R G B) の形式の文字列で色を指定する。
R, G, B
はそれぞれ赤、緑、青の成分で 0 から 255 の数値である。
以下にいくつかの例を示す。
rgb( 0 0 0)
rgb(127 0 0)
rgb(255 0 0)
rgb( 0 127 0)
rgb(127 127 0)
rgb(255 127 0)
rgb( 0 255 0)
rgb(127 255 0)
rgb(255 255 0)
rgb( 0 0 127)
rgb(127 0 127)
rgb(255 0 127)
rgb( 0 127 127)
rgb(127 127 127)
rgb(255 127 127)
rgb( 0 255 127)
rgb(127 255 127)
rgb(255 255 127)
rgb( 0 0 255)
rgb(127 0 255)
rgb(255 0 255)
rgb( 0 127 255)
rgb(127 127 255)
rgb(255 127 255)
rgb( 0 255 255)
rgb(127 255 255)
rgb(255 255 255)
また
rgb(R G B / A) の形式の文字列で
A にアルファ値(不透明度)を指定することもできる。
アルファ値は 0 から 1 の数で、0 が完全に透明、1 が完全に不透明を表す。
HSL は、色相(Hue)、彩度(Saturation)、明度(Lightness)で色を表現する方法である。
CSS では hsl(H S L) の形式の文字列で色を指定する。
H は色相で、0 から 360 の数値で表される。
0 が赤、120 が緑、240 が青を表す。
S は彩度で、0 % から 100 % で表される。
0% がグレー、100 % が最も鮮やかな色を表す。
L は明度で、0 % が黒、100 % が白を表す。
なお、最後に / A の形式を付け加えるとアルファ値も指定することができるのは RGB のときと同じである。
以下にいくつかの例を示す。
hsl(180 100% 50%)
hsl(120 100% 50%)
hsl( 60 50% 50%)
hsl(300 50% 80%)
hsl(240 25% 50%)
HSL は同じ明度、彩度であっても色相によって人間に感じられる明るさがかなり異なる、という欠点がある。このような欠点を解消するために提案されたのが OkLCh である。
OkLCh は、明度(Lightness)、彩度(Chroma)、色相(Hue)、で色を表現する方法である。
CSS では oklch(L C H) の形式の文字列で色を指定する。
L は明度で、0 % から 100 % で表される。
C は彩度で、0 % からのパーセントで表される。
H は色相で、0 から 360 の数値で表される。
彩度と明度を固定すると、人間の眼に“同じように”見える色相の変化を表現できる。
なお、最後に / A の形式… 。
以下にいくつかの例を示す。
oklch(50% 100% 180)
oklch(50% 100% 120)
oklch(50% 50% 60)
oklch(100% 50% 300)
oklch(50% 25% 240)
RGB, HSL, OkLCh のほかにも HWB や Lab などの色の表現方法があるが、ここでは説明を割愛する。
p5.js は、プログラミングの初心者でも容易に扱えるように設計された、 グラフィックスやアニメーションを作成するための JavaScript のライブラリーである。 Web ページ上のエディター(p5.js Web Editor)からでも簡単に作成して試すこともできる。p5.js Web Editor で実行するときにはバージョンの選択に注意する。この資料で紹介しているプログラムは、p5.js のバージョン 2.0.0 以降で動作するが、p5.js Web Editor は最初は古いバージョンが選択されていることがある。
ここでは HTML ページに p5.js で作成したグラフィックスを埋め込む方法を説明する。
まず、HTML の <head> ~ </head> タグの間に次のように書いて、
ライブラリーを読み込むようにする(2.2.2 のところは、その時点での適切なバージョンに置き換える)。
<script src='https://cdn.jsdelivr.net/npm/p5@2.2.2/lib/p5.min.js'></script>
さらに、<body> ~ </body> タグの間(の最後のほう)に次のようなコードを挿入する。
<script>
function setup() {
createCanvas(320, 180); // キャンバスのサイズを指定
}
function draw() {
background("lightgray"); // 背景色を設定
stroke("green");
fill("orange");
ellipse(200, 100, 180, 120);
}
</script>
このコードは以下のような画像を生成する。

function setup() { ... } は setup という関数を定義する部分である。... の部分は、p5.js のライブラリーによって自動的に最初に実行される。
通常はこの中でキャンバス(描画される領域)のサイズを指定して作成する。
デフォルトでは HTML 文書の末尾にキャンバスが追加される。
キャンバスの位置を変更したい場合は、HTML のなかに
<canvas id="myCanvas"></canvas> のように
canvas タグを先に作成しておき、createCanvas の第 3 引数としてそのキャンバス要素を指定する。
⋮
<canvas id="myCanvas"></canvas>
⋮
<script>
function setup() {
createCanvas(320, 180, document.getElementById("myCanvas"));
}
⋮
</script>
⋮
function draw() { ... } は draw という関数を定義する部分である。この ... の部分はページの描画のときに呼び出されるので、描画のためのプログラムの文を追加していく。
なお、この書き方では、1 つのウェブページに 1 つの絵(キャンバス)しか作成できない。 その場合、複数のウェブページを作成し、iframe タグを使って 1 つのページに読み込むようにする方法がある。 または、p5.js のインスタンスモードを使う方法もあるが、ここでは説明を割愛する。
描画のための関数としては、次のようなものがある。 ここでは主なものだけを紹介する。 p5.js のリファレンスにはもっとたくさんの関数が説明されている。
background(color): 背景の色を指定する。stroke(color): 線の色を指定する。fill(color): 塗りつぶしの色を指定する。strokeWeight(width): 線の太さを指定する。noStroke(): 線を描画しないようにする。noFill(): 塗りつぶしを行わないようにする。なお、色の指定の仕方はいろいろあるが、上の CSS Color で説明した形式をそのまま文字列として指定することができる。例えば、
stroke("hsl(180 100% 50%)") のように書くことができる。
line(x1, y1, x2, y2):
2 点 (x1, y1) – (x2, y2) を結ぶ線分を描画する。rect(x, y, w, h):
(x, y) に幅 w と高さ h の長方形を描画する。
デフォルトでは、(x, y) は左上の点である。ellipse(x, y, w, h):
(x, y) に w と高さ h の楕円を描画する。
デフォルトでは、(x, y) は楕円の中心である。arc(x, y, w, h, startAngle, endAngle):
(x, y) を中心として、幅 w と高さ h の楕円の一部を描画する。
デフォルトでは startAngle と endAngle はラジアンで指定する。triangle(x1, y1, x2, y2, x3, y3):
3 点 (x1, y1)–(x2, y2)–(x3, y3)を結ぶ三角形を描画する。quad(x1, y1, x2, y2, x3, y3, x4, y4):
4 点を結ぶ四角形を描画する。以下にこれらの関数の一部を使った例を示す。
<script>
function setup() {
createCanvas(320, 180); // キャンバスのサイズを指定
}
function draw() {
background("lightgray");
noFill();
stroke("red");
line(25, 25, 125, 75);
stroke("green");
rect(25, 25, 100, 50);
stroke("blue");
fill("orange");
ellipse(200, 50, 120, 60);
noStroke();
fill("cyan");
triangle(50, 170, 200, 170, 100, 120);
fill("magenta");
triangle(75, 160, 225, 160, 125, 110);
fill("yellow");
triangle(100, 150, 250, 150, 150, 100);
}
</script>
このプログラムは以下のような画像を生成する。

なお、以降の例では、function setup() { ... } の部分は変わらないので、
function draw() { ... } の中身(... の部分)だけを示すことにする。
以下に、p5.js を使ったグラフィックスのプログラム例をいくつか示す。 まずは繰り返しを使った例である。
noStroke();
for (y = 0; y < 180; y += 10) {
for (x = 0; x < 320; x += 10) {
fill(`oklch(90% ${100 - x / 3.2}% ${y * 2})`);
ellipse(x + 5, y + 5, 8, 8);
}
}

文字列(テキスト)の描画関数も用意されている。
text(text, x, y):
(x, y) に文字列を描画する。デフォルトでは (x, y) は文字列の左下の点である。textSize(size):
文字列のフォントのサイズを指定する。textFont(font):
文字列のフォントを指定する。文字列には絵文字を含めることも可能である。
random(m, n):
m 以上 n 未満のランダムな実数値を生成する。なお、一つの数値の引数を指定する
(rand(m))と、0 以上 m 未満のランダムな実数値を生成する。random(array):
唯一の引数が配列のときは、配列 array の要素のうち、ランダムに一つを選んで返す。noLoop():
draw() 関数の繰り返しを止める。これにより draw() 関数は一度だけ実行される。cos(angle):
angle の余弦を返す。デフォルトでは angle はラジアンで与える。
同様に sin や tan もある。atan(value):
value の逆正接(デフォルトではラジアン)を返す。
同様に acos や asin もある。atan2(x, y):
原点 (0, 0) から (x, y) に向かう半直線が
x 軸の正の方向となす角(デフォルトではラジアン)を返す。最後にこれらの関数を使ったいくつかの p5.js のプログラム例を示す。
const n = 100;
const fruits =["🍏", "🍑", "🍇", "🍐"];
textSize(10);
for (let count = 0; count < n; count++) {
let r = 20 + count / n * 70, t = count * 19;
let x = 160 + 1.6 * r * cos(t / 180 * 3.14),
y = 100 + r * sin(t / 180 * 3.14);
text(fruits[count % fruits.length], x, y);
}

textSize(18);
const chars = ["か", "が", "わ", "だ", "い", "が", "く"];
for (let x = 0; x < 320; x += 20) {
for (let y = 0; y < 180; y += 20) {
let h = random(360);
fill(`oklch(50% 100% ${h})`);
let c = random(chars);
text(c, x, y + 20);
}
}
noLoop(); // draw() は一度だけ実行する

noStroke();
for (let i = 0; i < 300; i++) {
const x = random(5, 315);
const y = random(5, 175);
const h = random(0, 360);
let a = 1;
if ((x - 160) * (x - 160) * 0.316 + (y - 90) * (y -90) > 4900) {
a = 0.1;
}
fill(`oklch(80% 70% ${h} / ${a})`)
ellipse(x, y, 10, 10);
}
noLoop();

マウスクリックに対するインタラクションやアニメーションなども記述できるので、ぜひ p5.js のリファレンスを調べてほしい。
ここまで解説した function setup() { ... } と function draw() { ... } を定義する方法は、p5.js のグローバルモードと呼ばれるものである。この方法は簡単だが、1 つのウェブページに 1 つの絵(キャンバス)しか作成できない。
複数のキャンバスを作成したい場合は、iframe を使う方法と p5.js のインスタンスモードを使う方法がある。ここではインスタンスモードの書き方を紹介する。 最初の例をインスタンスモードで書くと次のようになる。
const sketch = (p) => {
p.setup = function() {
p.createCanvas(320, 180);
};
p.draw = function() {
p.background("lightgray");
p.stroke("green");
p.fill("orange");
p.ellipse(200, 100, 180, 120);
};
};
new p5(sketch, "div1");
つまり、
function setup() { … } と function draw() { … } を、
const sketch = (p) => { p.setup = () => { … }; p.draw = () => { … }; }; new p5(sketch, "div1");
という形に書き換え、さらに … の内部の createCanvas や background などの p5.js の関数を p.createCanvas、p.background のように p.~ の形に書き換える。
最後の new p5(sketch, "div1"); の部分は、HTML のなかに <div id="div1"></div> のように div タグを作成してあったとして、その div タグの最後にキャンバスを追加する。第 2 引数を省略して new p5(sketch); とすると、ページの末尾にキャンバスが追加される。
JavaScript は DOM (Document Object Model) と呼ばれる仕組みを使って、 HTML 文書の要素を操作することができる。 DOM は、HTML 文書を JavaScript のオブジェクトとして表現したものである。
以下では DOM が提供する膨大なメソッド・プロパティーのうち、 使用頻度の高いものをごく一部選んで紹介する。
この節で紹介するプログラム例はDOM 操作プログラム例のページで実際に動かすことができる。
document オブジェクトは、HTML に読み込まれる JavaScript のコードに最初から用意される、現在の HTML 文書を表すオブジェクトである。このオブジェクトを通じて JavaScript から DOM を操作する。
document オブジェクトが提供するメソッドとして次のようなものがある。
document.createElement(tagName): 指定されたタグ名の要素を作成する。document.getElementById(id):
指定された ID を持つ要素を取得する。id="..." という属性で付けられる一意の名前である。document.querySelectorAll(selector):
指定された CSS セレクターに一致するすべての要素のリストを取得する。
CSS セレクターは HTML の要素を絞り込むための記法で、例えば次のようなものが使用できるが、そのほかにもさまざまな
CSS セレクターがある。詳しくは、MDN の
CSS セレクターを読むと良い。
"tagName":
一般にタグ名を指定するとそのタグのすべての要素にマッチする
例えば "li" だと <li> タグのすべての要素にマッチする".className": ドット . のあとにクラス名を指定すると、
そのクラス className を持つすべての要素にマッチする。上の getElementById や querySelectorAll で取得した要素は、Element
と呼ばれるクラスに属するオブジェクトである。
Element オブジェクトは次のようなメソッドやプロパティーを持つ。
詳細は MDN の Element を読むと調べることができる。
element.append(child):
要素 element の最後の子要素の後に要素 child を追加する。element.prepend(child):
要素 element の最初の子要素の前に要素 child を追加する。element.insertAjacentHTML(position, text) :
要素 element の指定された位置に
text を HTML として解釈して挿入する。
position は "afterbegin"、"beforeend" などで、
前者は最初の子要素の前、後者は最後の子要素の後、を表す。element.querySelectorAll(selector):
要素 element の子孫のうち、指定された
CSS セレクターに一致するすべての要素のリストを取得する。 innerHTML と style は Element のプロパティーである。
element.innerHTML:
要素 element の内容を HTML として解釈した文字列を取得または設定する。element.style:
要素 element のスタイルを表すオブジェクトである。
このオブジェクトのプロパティーから CSS のスタイルを設定することができる。
例えば、element.style.color = "red"; とすると、要素の文字色を赤にする。次のプログラムはinsertAdjacentHTML メソッドの使用例である。
⋮
<p id="gradation"></p>
⋮
<script>
const gradation = document.getElementById("gradation");
for (let i = 0; i < 360; i += 15) {
const color = `oklch(80% 100% ${i})`;
gradation.insertAdjacentHTML("beforeend",
`<span style="color: ${color};">█</span>`);
}
</script>
⋮
出力結果は次のようになる。
████████████████████████
多次元配列と for ~ of 文を使っている例を示す。
⋮
<p id="squares"></p>
⋮
<script>
const board = [["blue", "white", "red"],
["black", "yellow", "red"],
["orange", "white", "green"]];
const squares = document.getElementById("squares");
for (let row of board) {
for (let color of row) {
squares.insertAdjacentHTML("beforeend",
`<span style="color: ${color};">█</span>`);
}
squares.insertAdjacentHTML("beforeend", "<br>");
}
</script>
⋮
出力結果は次のようになる。
███
███
███
addEventListener は、要素にイベントの処理を追加するためのメソッドである。value
は、入力用の要素の値を取得するためのプロパティーである。
element.addEventListener(event, callback):callback を登録する。 element.value:ボタンの場合は、次のように"click"に対してイベント処理を記述する。
⋮
<button id="my-button">Click!</button>
⋮
<script>
const myButton = document.getElementById("my-button");
myButton.addEventListener("click", ev => {
// ここにクリックされたときの処理を書く
// ⋮
});
</script>
⋮
ev => { ... } はアロー関数式という関数の書き方であるが、詳しい説明は省く。
とにかく ... の部分に、イベントが発生したときに実行したい処理を書けば良い。
また input 要素の値を取得して処理する場合は、次のように"change"イベントに対して処理を書く。
⋮
<input id="my-input" type="text" value="nanika">
⋮
<script>
const myInput = document.getElementById("my-input");
myInput.addEventListener("change", ev => {
const text = myInput.value; // 入力された文字列
// ここに text を使った処理を書く
// ⋮
});
</script>
⋮
button の click イベントを使ったプログラムの例を示す。
⋮
<button id="clickbtn">Click!</button>
⋮
<script>
const clickbtn = document.getElementById("clickbtn");
clickbtn.addEventListener("click", ev => {
clickbtn.insertAdjacentHTML("beforeend", "!");
if (clickbtn.innerHTML.length > 15) {
clickbtn.innerHTML = "Click!";
}
});
</script>
⋮
このボタンを何度かクリックしたときの見た目は次のようになる。
クリックするたびに ! が増えていくが、
さらに何度かクリックすると Click! に戻る。
⋮
入力: <input type="text" id="cname" size="10"><br>
入力 (<span id="cdisplay"></span>) は
<span id="validity">無効な</span>色です。</p>
<script>
const cname = document.getElementById("cname");
const cdisplay = document.getElementById("cdisplay");
const validity = document.getElementById("validity");
cname.addEventListener("change", ev => {
const color = cname.value;
cdisplay.innerHTML = color;
if (color && CSS.supports("color", color)) {
cdisplay.style.color = color;
cdisplay.style.backgroundColor = null;
validity.innerHTML = "有効な";
} else {
cdisplay.style.color = "white";
cdisplay.style.backgroundColor = "red";
validity.innerHTML = "無効な";
}
});
</script>
⋮
このプログラムは、input 要素に入力された文字列が有効な色であるかどうかをチェックし、結果を表示する。
このプログラムで使われているメソッド CSS.supports("property", value) は、
現在のブラウザーで
CSS のプロパティー property が
値 value をサポートしているかどうかを調べるメソッドである。
green のような有効な色名を入力すると、次のように表示される。
green 一方で nocolor のような無効な色名を入力すると、次のように表示される。
nocolor ⋮
<input type="number" id="finput" value="0" min="0" max="22">
の階乗は <span id="fresult">1</span> です
⋮
<script>
const finput = document.getElementById("finput");
const fresult = document.getElementById("fresult");
finput.addEventListener("change", ev => {
const input = finput.value;
let result = 1;
for (let i = 2; i <= input; i++) {
result *= i;
}
fresult.innerHTML = result;
});
</script>
⋮
このプログラムは、入力された数の階乗 (factorial) を計算して表示する。
input 要素に例えば 10 を入力すると次のように表示される。 (type=”number” の input 要素にはスピナーと呼ばれる増減のための小さなボタンが付くときもある。)
10
の階乗は 3628800 です。
⋮
色を選択: <input type="color" id="cpicker" value="#ff0000"><br>
選択した色は <code id="cstring">#ff0000</code> です。
⋮
<script>
const cpicker = document.getElementById("cpicker");
const cstring = document.getElementById("cstring");
cpicker.addEventListener("change", ev => {
const color = cpicker.value;
cstring.innerHTML = color;
cstring.style.color = "white";
cstring.style.backgroundColor = color;
});
</script>
⋮
このプログラムは、input 要素で選択された色を表す文字列を表示する。選択すると、次のような表示になる。
#ac27d8 です。
CSS Color Module Level 4 によると 148 種類ある。2014 年に追加された rebeccapurple が最後らしい。 ↩