マウスの位置に応答する
マウスの移動やボタン押下などの操作に応答させることで、インタラクションのあるスケッチを作成できます。 ここでは、マウスの位置に応じた応答をするサンプルを考えます。マウスの位置
マウスの位置は、p5.jsがあらかじめ定義している変数(システム変数)に保存されています。mouseX 現在のマウスの水平方向の座標 mouseY 現在のマウスの垂直方向の座標マウスの位置に円を描いてみましょう。setup()関数内に画面の大きさ設定など1度だけ実行する処理を書き、draw()関数内に応答させる処理を書きます。
【リストT2-3-1】 function setup() { createCanvas(250, 125); stroke(200, 0, 0); //線の色を赤に設定 background(240); //背景をグレーに塗る } function draw() { ellipse(mouseX, mouseY, 10, 10); //直径10の円をマウスの位置に描く }
右側の灰色のキャンバス上でマウスを動かしてください。円が重なって、描かれます(最初,座標の原点(0,0)である左上角に円があります)。draw()関数は、指定されたフレームレート(デフォルトで60回/秒)で、繰返し実行されます。それにより、ellipse()関数が繰返し実行され、その結果として円が描かれます。 重なって描かれるのは、同じ画用紙であるキャンバス上に描画しているからです。1つ円を描くごとに、新しい画用紙を使えば、1つの円が動いているように見えます。 draw()関数の実行ごと(つまりフレームごと)に background()関数を使って、キャンバスを背景色で塗れば、それが実現できます。
前のフレームでのマウスの位置、つまり前のdraw()の実行時のマウスの位置も保存されています。
pmouseX 前のdraw()の実行時(前のフレーム)のマウスの水平方向の位置 pmouseY 前のdraw()の実行時(前のフレーム)のマウスの垂直方向の位置さらに、前のフレームのマウスの位置と現在のマウスの位置の差もシステム変数に保存されています。
movedX 前のdraw()の実行時(前のフレーム)からのマウスの水平方向の変化 movedY 前のdraw()の実行時(前のフレーム)からのマウスの垂直方向の変化ellipse関数の引数の円の幅、高さを次のように指定すると、マウスの移動距離に応じた楕円が描かれます。
ellipse(mouseX, mouseY, movedX, movedY);
キャンバス上の位置とマウスとの距離
キャンバス上の特定の範囲に、マウスが移動した時に、なんらかの応答をさせる場合、マウスとその位置との距離を計算する必要があります。それには、dist()を使います。dist(mouseX, mouseY, その位置のx座標, その位置のy座標)リストT2-1-1で、寿命を表す円の上にマウスが入ったら、その円に対応する生物の平均寿命を表示させることを考えます。マウスの円の中心からの距離を計算し、それが円の半径より小さければ、マウスが円に入ったと判断できます。
【リストT2-3-2】 //定数、変数の設定、setup()関数はT2-1-1と同じ function draw() { background(240); for (let i=0; i<span.length; i++) { let d = map(span[i], 1, 100, min, max); //円の大きさ let x = cx + i*distance; //円を描くx座標 fill(200, 0, 0); ellipse(x, cy, d, d); fill(0); textSize(12); text(name[i], x, cy+max); if (dist(mouseX, mouseY, x, cy) < d/2) { //マウスが円内に入ったら、 textSize(16); //フォントサイズを大きくして text(span[i]+"年", x, cy); //文字を円の中心に描く } } }
マウスボタンが押されている時に応答
リストT2-3-2で、マウスが円の中に入り、かつマウスボタンが押されている時だけ応答するように修正したのが、次のスケッチです。マウスボタンが押されているかどうかは、システム変数mouseIsPressedに保存されています。
mouseIsPressed マウスボタンが押されている時true、そうでない時はfalseマウスが円内にあるかどうかに加え、mouseIsPressedの値がtrueかを調べて、その時だけ円の色を変え、寿命を表示しています。
【リストT2-3-3】 //定数、変数の設定、setup()関数はT2-1-1と同じ function draw() { background(240); for (let i=0; i<span.length; i++) { let d = map(span[i], 1, 100, min, max); //円の大きさ let x = cx + i*distance; //円を描くx座標 fill(0); textSize(12); text(name[i], x, cy+max); if (dist(mouseX, mouseY, x, cy) < d/2 && mouseIsPressed) { textSize(16); text(span[i]+"年", x, cy); fill(200, 100); //円の色をグレー、アルファ値(透明度)を指定 } else { fill(200, 0, 0); } ellipse(x, cy, d, d); } }
演習問題
【問題T2-3-1】問題T2-1-1で表示した棒グラフで、マウスが矩形内に入った時に、平均寿命を矩形の上部に表示するように変更してみよう。
リストT2_3_2と違い、単純な距離ではなく、マウスの位置が矩形内かどうかを調べる必要があります。
その条件を書くと次のようになります。
- mouseXが矩形左辺のx座標よりも大きく(mouseX>x)
- mouseXが右辺のx座標よりも小さく(mouseX<x+rw)
- mouseYが上辺のy座標より大きく(mouseY>y-rh)
- mouseYが下辺のy座標より大きい(mouseY<y)。