この記事は Qiita p5js アドベントカレンダー3日目の記事です。
これはなに
書籍『Generative Design with p5.js』P_1_2_1_01に登場する関数について理解を深める記事です。
今回はmap()。
map()
mapといえば他の言語だと配列操作の印象がありますが、
p5のmap関数は全然違う目的で使用されるようです。
Type
map(
value: number,
start1: number,
stop1: number,
start2: number,
stop2: number,
withinBounds?: boolean
): number;
引数については下記の通り。
- value 動的な値
- start1 valueの下限
- stop1 valueの上限
- start2 valueの下限に対して返す値の下限
- stop2 valueの上限に対して返す値の上限
- withinBounds trueのとき、stop2の値を超えることがなくなるオプション
↑
mapを理解してこれを書くまで結構苦しみました。
リファレンスより
Re-maps a number from one range to another.
In the first example above, the number 25 is converted from a value in the range of 0 to 100 into a value that ranges from the left edge of the window (0) to the right edge (width).数値をある範囲から別の範囲に再マッピングします。
上の最初の例では、25という数字は、0から100の範囲の値から、ウィンドウの左端(0)から右端(幅)までの範囲の値に変換されます。(DeepL翻訳)
これだけではわからん(素直な気持ち)
試してみる
リファレンスを参考に下記のコードを試してみました。
コンソールにポインタのX座標とmapの結果を出力します。
(Vueで使用しているため関数の前に'p'があります)
p.setup = () => {
p.createCanvas(500, 500);
// p.colorMode(p.HSB);
};
p.draw = () => {
p.background(204);
let x1 = p.map(p.mouseX, 0, p.width, 25, 75);
console.log(`mouseX: ${p.mouseX} x1: ${x1}`);
p.ellipse(x1, 25, 25, 25);
};
出力結果がこちら。
mouseXが522のとき、mapの結果は77.2と出ています。
mouseX: 522 x1: 77.2
mapの結果はellipse()の第一引数にセットされているため、
ポインタが横に動けば描画された楕円も横に動きます。
p.ellipse(x1, 25, 25, 25);
では何がおこっているのか。
まずstart1は0、stop1はwidthです。
つまりmapにおけるvalueの開始地点は0、
終着地点は500となります。
それを踏まえてstart2とstop2の結果が返る値となります。
start2は25、ということはmouseX(value)が0のときに25を返します。
stop2は75なので、mouseX(value)が500(width)のときに75を返します。
ここでもう一度コンソールに出力した結果を確認しましょう。
mouseX: 522 x1: 77.2
ポインタのX座標が522、x1が77.2と出ています。
つまり、現在のポインタはcreateCanvasの範囲からはみ出た場所におり、
targetの位置もstop2の値を少し超えた場所に位置しているということになります。
今回はつけていないですが、第五引数のwithinBounds
にtrueを渡せば
mouseXが500を超えても、mapの返り値は75でストップします。
いやー難しかった!!
どんなときに使えそうか
「変動する値をもって、範囲を指定したい別の値に置き換えたいとき」
でいいんじゃないでしょうか。
実際にP_1_2_1_01で使用している箇所をみてみましょう。
tileCountX = int(map(mouseX, 0, width, 2, 100));
tileCountY = int(map(mouseY, 0, height, 2, 10));
リンクから挙動を試してみてください。
横軸の正確な目視は難しいですが、
マウスが右いっぱいの時にタイルの数が1行に対して100列、
マウスが下いっぱいの時にタイルが10行になっていることが分かります。
動的な要素で制御したいときはmap()の使用を検討してみると
面白い動きができるかもしれませんね。
参考
p5.js reference | map()
『Generative Design with p5.js』P_1_2_1_01