アリソンパリッシュによる
p5.jsフレームワークを使用すると、スケッチを含むページに、HTML5のインターフェース要素が簡単に追加できます。追加したインターフェース要素を使用すると、ユーザーがスケッチを制御できるようになります。本チュートリアルではこの方法を見ていきます。
目次
p5.jsとブラウザ
すべてのp5.jsスケッチは実際には、Webページ内にあるただの”キャンバス要素”です。ここまで見てきたサンプルのページにはスケッチがあるだけで、ほかには何もありませんでした。しかし実際には、そのページに希望するものを含めることができます。HTMLをご存知なら、p5.jsがエクスポートするindex.htmlファイルに直接手を加えることもできます。
しかしp5.jsスケッチのブラウザ特性(ブラウザと親密な関係にあること)を使用すると、ただの飾り以上のものが作り出せます。ボタンや入力ボックス、スライダーといったインターフェース要素は以前から、インタラクティブなソフトウェアを作成するときの最も難しい部品の1つです。しかしすべてのp5.jsスケッチはWebブラウザの中に存在するので、ブラウザに組み込まれているインターフェース要素が利用できます。すると、自分で作成する必要がなくなるので、大きな時間節約になります。
このチュートリアルのサンプルを動作させるには、p5.domライブラリが必要になります。これは、スケッチとスケッチを含むWebページ間のやりとりを可能にするものです(スケッチをp5アプリで作成するときにはデフォルトで含まれますが、HTML/JavaScriptファイルで動作させる場合には、別に読み込む必要があります)。
メモ
p5.domライブラリをHTMLファイルに読み込むとき、次のCDNを使った<script>タグが利用できます。
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/addons/p5.dom.min.js"></script>
各ライブラリのバージョンはここで確認できます。
ボタンの追加
スケッチへのボタンの追加は簡単で、createButton()関数を呼び出すだけです。
let button;
function setup() {
createCanvas(400, 300);
button = createButton("Hello");
background(50);
}
function draw() {
}
なかなかナイスなボタンです。しかしこれをクリックしても何も起こりません。インターフェース要素に特定の振る舞いを割り当てるには、ユーザーがボタンをクリックしたときに実行したいコードを含む関数を定義し、そしてユーザーが特定のアクションを取ったときにp5.jsにその関数を呼び出すように伝える”イベントリスナー”を、そのオブジェクト(ボタン)に割り当てる必要があります。
let button;
function setup() {
createCanvas(400, 300);
// ボタンを作成
button = createButton("Click me!");
// ボタンにマウスが押されたときのイベントリスナーを追加する。
// ボタンが押されたらrandomRectangle()を呼び出す
button.mousePressed(randomRectangle);
background(50);
noStroke();
}
function draw() {}
function randomRectangle() {
fill(random(255));
rect(random() * width, random() * height,
random(400), random(400));
}
createButton()関数は、ボタンオブジェクト(実際にはp5.Elementオブジェクト)を返します。このオブジェクトや、以降で見ていくほかの…create()関数が返すオブジェクトは、.mousePressed()という名前のメソッドをサポートしています。.mousePressed()メソッドに渡すパラメータには、ユーザーがそのボタンをクリックしたときに、p5.jsに呼び出させたい関数の名前を指定します。
ボタンの追加は1つに限りません。次のスケッチでは、2つめのボタンを追加し、mousePressedイベントを処理する2つめの関数を設定しています。
let button1;
let button2;
function setup() {
createCanvas(400, 300);
button1 = createButton("Click me!");
button1.mousePressed(randomRectangle);
button2 = createButton("Clear");
button2.mousePressed(clearEverything);
background(50);
noStroke();
}
function draw() {}
function randomRectangle() {
fill(random(255));
rect(random() * width, random() * height,
random(400), random(400));
}
function clearEverything() {
background(50);
}
スライダー
もう1つの便利なインターフェース要素はスライダーです。スライダーを使用すると、ユーザーが、視覚的なフィードバックを得ながら、1つの値を範囲内から指定することができます。スケッチのページにスライダーを追加するには、createSlider()関数を使用します。
let slider;
function setup() {
createCanvas(400, 300);
slider = createSlider(0, width, width / 2);
}
function draw() {
background(50);
fill(255);
noStroke();
ellipse(slider.value(), height / 2, 50, 50);
}
スライダーオブジェクトの.value()メソッドは、スライダーの現在の値を返します。上記サンプルでは、円のX位置の制御に使用しています。createSlider()関数は、スライダーの最小値と最大値、初期値の3つのパラメータを取り、スライダーを作成します。
次のサンプルでは、楕円のサイズを制御する2つめのスライダーを追加しています。
let positionSlider;
let sizeSlider;
function setup() {
createCanvas(400, 300);
positionSlider = createSlider(0, width, width / 2);
sizeSlider = createSlider(0, 255, 0);
}
function draw() {
background(50);
fill(255);
noStroke();
ellipse(positionSlider.value(), height / 2,
sizeSlider.value(), 50);
}
スライダーは読み取り専用ではありません。.value()メソッドにパラメータを与えて呼び出すことで、データを表示する方法としても使用できます。次のサンプルでは、サイン波のパターンでスライダーを動かしています。
let slider;
function setup() {
createCanvas(400, 300);
slider = createSlider(-100, 100, 0);
}
function draw() {
background(50);
fill(255);
noStroke();
var sinVal = sin(frameCount * 0.05);
ellipse(width / 2, height / 2, (1 + sinVal) * 100, (1 + sinVal) * 100);
slider.value(sinVal * 100);
}
テキスト入力フィールドの作成
テキスト入力は、インターフェース設計において最も難しい問題の1つです。ブラウザのビルトイン テキスト入力インタフェース要素を活用しましょう。自分でゼロから記述する必要がなくなります。
そのためには、createInput()関数を呼び出します。createInput()関数は、ページに新しいテキスト入力要素を作成します。createInput()に渡す値が、テキストフィールドの初期値を設定します。テキストフィールドでも、スライダーと同じように、フィールドのvalue()メソッドを使って、ユーザーがフィールドに入力したものが取得できます。
let field;
function setup() {
createCanvas(400, 300);
field = createInput("ここに入力してください");
}
function draw() {
background(50);
fill(255);
noStroke();
textSize(24);
text(field.value(), 10, 10, width - 20, height - 20);
}
次のスケッチは、テキスト入力フィールドとボタンを組み合わせ、ユーザー入力を使って”爆発するテキスト”効果を作成する、より高度な例です。
let field;
let button;
let letters = [];
function setup() {
createCanvas(400, 300);
field = createInput("your text");
button = createButton("Explode!!");
button.mousePressed(explodeText);
}
function draw() {
background(50);
fill(255);
noStroke();
textSize(24);
for (var i = 0; i < letters.length; i++) {
text(letters[i].letter, letters[i].xpos,
letters[i].ypos);
letters[i].xpos += letters[i].xdir;
letters[i].ypos += letters[i].ydir;
}
}
function explodeText() {
textSize(24);
var text = field.value();
var currentPos = random(width / 2);
for (var i = 0; i < text.length; i++) {
var letterObj = {
letter: text.charAt(i),
ypos: 50,
xpos: currentPos,
xdir: random(-1, 1),
ydir: random(-0.5, 2)
};
letters.push(letterObj);
currentPos += textWidth(text.charAt(i));
}
}