p5.jsの続きです。前回は「Generative Design with p5.js」の「P.4. 画像」の「01」を見ました。今回は画像編「P.2. 形」の「02」「03」を見ていきます*1。それでは行きましょう!
【目次】
※参考:【p5.js】Generative Design with p5.js「画像 P_4_0_01」のコードを読み解く - クモのようにコツコツと
※p5.jsを習得するためにやったことまとめ
【ビジュアルコーディング】p5.jsを習得するためにやった事 まとめ(随時更新) - Qiita
形 P_2_0_02
完成品
書籍「Generative Design with p5.js」より
![Generative Design with p5.js - [p5.js版ジェネラティブデザイン] ―ウェブでのクリエイティブ・コーディング Generative Design with p5.js - [p5.js版ジェネラティブデザイン] ―ウェブでのクリエイティブ・コーディング](https://m.media-amazon.com/images/I/51m7zcdhX9L._SL160_.jpg)
Generative Design with p5.js - [p5.js版ジェネラティブデザイン] ―ウェブでのクリエイティブ・コーディング
- 作者:Benedikt Gross,Hartmut Bohnacker,Julia Laub
- 発売日: 2018/06/22
- メディア: 単行本
ソースコード一覧
※参考:Generative Design with p5.js[p5.js版ジェネラティブデザイン] ―ウェブでのクリエイティブ・コーディング
形 P_2_0_02
最初は何もないが、キャンバス上をクリックすると図形が現れる。ドラッグで連続描写。左右で多角形の角数が変わる。左右で線の太さと数が変わる。
JSコード全体
// P_2_0_02 // // Generative Gestaltung – Creative Coding im Web // ISBN: 978-3-87439-902-9, First Edition, Hermann Schmidt, Mainz, 2018 // Benedikt Groß, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni // with contributions by Joey Lee and Niels Poldervaart // Copyright 2018 // // http://www.generative-gestaltung.de // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * drawing with a changing shape by draging the mouse. * * MOUSE * position x : length * position y : thickness and number of lines * drag : draw * * KEYS * del, backspace : erase * s : save png */ 'use strict'; function setup() { createCanvas(720, 720); noFill(); background(255); strokeWeight(2); stroke(0, 25); } function draw() { if (mouseIsPressed && mouseButton == LEFT) { push(); translate(width / 2, height / 2); var circleResolution = int(map(mouseY + 100, 0, height, 2, 10)); var radius = mouseX - width / 2; var angle = TAU / circleResolution; beginShape(); for (var i = 0; i <= circleResolution; i++) { var x = cos(angle * i) * radius; var y = sin(angle * i) * radius; vertex(x, y); } endShape(); pop(); } } function keyReleased() { if (keyCode == DELETE || keyCode == BACKSPACE) background(255); if (key == 's' || key == 'S') saveCanvas(gd.timestamp(), 'png'); }
冒頭コメントの前半はクレジット。 後半の概要の訳。
マウスをドラッグして、形を変えながら描画します。
マウス 位置x:長さ 位置y:太さと線の数 ドラッグ:描画
キー del、backspace:消去 s:pngを保存
全体構成
まずは大枠部分
function setup() { // ページ読み込み時の処理 } function draw() { // 一定時間ごとに繰り返し実行 } function keyReleased() { // キーが離れた時の処理 }
この3つのメソッドは基本的にこれまでと同じ構成。
※参考:【ビジュアルコーディング】p5.jsを習得するためにやった事 まとめ(随時更新) - Qiita
setup()の中身
ページ読み込み時の処理
function setup() { createCanvas(720, 720); noFill(); background(255); strokeWeight(2); stroke(0, 25); }
createCanvas()でキャンバス作成。720px幅、720px高さnoFill()で塗りを無しにbackground()で背景色設定。RGB共に#255stroke()でグレースケールを0、透明度を25%に
noFill()は塗りなしの設定
Disables filling geometry. If both noStroke() and noFill() are called, nothing will be drawn to the screen.
ジオメトリの塗りつぶしを無効にします。 noStroke()とnoFill()の両方が呼び出された場合、画面には何も描画されません。
stroke()は線の設定で引数が2つの場合はグレースケース、透明度の設定になる。
stroke(gray, [alpha])
これらが読み込み時の初期設定
draw()の中身
draw()全体
一定時間ごとに繰り返し実行
function draw() { if (mouseIsPressed && mouseButton == LEFT) { push(); translate(width / 2, height / 2); var circleResolution = int(map(mouseY + 100, 0, height, 2, 10)); var radius = mouseX - width / 2; var angle = TAU / circleResolution; beginShape(); for (var i = 0; i <= circleResolution; i++) { var x = cos(angle * i) * radius; var y = sin(angle * i) * radius; vertex(x, y); } endShape(); pop(); } }
ここが本体なので部分ごとに見ていく
外側のif文
まず処理の全体をif文が囲っている。
if (mouseIsPressed && mouseButton == LEFT) { // 処理 }
- もしマウスが押されていて、かつ左クリックだったら、処理を実行する
mouseIsPressedはマウスが押されているかいないかを判定
The boolean system variable mouseIsPressed is true if the mouse is pressed and false if not.
ブールシステム変数mouseIsPressedは、マウスが押されている場合はtrue、押されていない場合はfalseです。
mouseButtonはどのボタンが押されているかをお判定
Processing automatically tracks if the mouse button is pressed and which button is pressed.
処理は、マウスボタンが押されたかどうか、およびどのボタンが押されたかを自動的に追跡します。
右クリックの場合は実行したくないようだ。自分の環境はMacなのでControlを押しながらクリックしたら右クリックメニューが立ち上がった。この動きが想定通りなのかな?
メソッド実行(push()、translate())
処理の冒頭でメソッドを実行している
push();
translate(width / 2, height / 2);
push()メソッド実行translate()メソッド実行。引数は第1引数は幅の半分、第2引数は高さの半分
push()メソッドはpop()メソッドとセットで使うようだ。
The push() function saves the current drawing style settings and transformations, while pop() restores these settings. Note that these functions are always used together.
push()関数は現在の描画スタイル設定と変換を保存し、pop()はこれらの設定を復元します。 これらの関数は常に一緒に使用されることに注意してください。
translate()メソッドは「形 P_2_0_01」でも出てきた、オブジェクトの移動量の設定をするメソッド。
※参考:【p5.js】Generative Design with p5.js「形 P_2_0_01」のコードを読み解く - クモのようにコツコツと
それぞれ、幅、高さ共にキャンバスの半分に設定している。
変数circleResolution
次に変数がいくつか設定されている。だんだん数学的になってきたので細かく見る。
var circleResolution = int(map(mouseY + 100, 0, height, 2, 10));
- 変数
circleResolutionでint()メソッド実行。引数はmap()メソッドで、その引数は左からマウスの縦位置+100px、0、高さ、2、10
メソッドが入れ子になってて直感的ではないw
circleResolutionは「サークル解像度」という意味。
値のint()メソッドは「形 P_2_0_01」でも出てきた。少数を切り捨てて整数にするメソッド。
※参考:【p5.js】Generative Design with p5.js「形 P_2_0_01」のコードを読み解く - クモのようにコツコツと
で、その中のmap()も同記事にあるが、値と値を関連づける(マッピング)メソッド。これで何と何を関連付けているのか
map(value, start1, stop1, start2, stop2, [withinBounds])
- 第1引数は入力値
- 第2、3引数は値の現在の範囲
- 第4、第5引数は値のターゲットの範囲
改めてmap()メソッド部分をみると
map(mouseY + 100, 0, height, 2, 10)
- マウスの縦位置に100px足した数値が入力値
- 値の現在の範囲は0からキャンバス高さ
- 値のターゲット範囲の下限は2、上限は10
マウスの縦位置に100pxを足した数値のうち、0〜キャンバス高さまでの範囲が2〜10に変換される。
変数radius
var radius = mouseX - width / 2;
- 変数
radiusの値はマウスの横位置から幅の半分を引いた数値
radiusは半径という意味。
変数angle
var angle = TAU / circleResolution;
- 変数
angleはTAUをcircleResolutionで割った数値
angleは角度。
TAUも「形 P_2_0_01」で出てきた。「2π」と同じ意味。circleResolutionで割るのも前回と共通。
※参考:【p5.js】Generative Design with p5.js「形 P_2_0_01」のコードを読み解く - クモのようにコツコツと
beginShape()〜endShape()
そのつぎはbeginShape()からendShape()に囲われたfor文がある
beginShape();
// for文
endShape();
beginShape()で形状を作成- 中にはfor文
endShape()で形状作成を終了
beginShape()〜endShape()は前回出てきた。形状を作成。
※参考:【p5.js】Generative Design with p5.js「色 P_1_0_03」のコードを読み解く - クモのようにコツコツと
for文
for文の中にサインコ・サイン!また三角関数だ!
for (var i = 0; i <= circleResolution; i++) { var x = cos(angle * i) * radius; var y = sin(angle * i) * radius; vertex(x, y); }
- for文の条件1:変数
iの初期値は0、条件2:iはcircleResolutionまで繰り返す、条件3:iを1ずつ加算 - 変数
xはangleにiを掛けたコサインとradiusを掛ける - 変数
yはangleにiを掛けたサインとradiusを掛ける vertex()メソッド実行。第1引数はx、第2引数はy
変数x、yは前回の「形 P_2_0_01」と共通している
三角関数「角度から座標(位置)を割り出す」の公式になる!
- 半径の長さrとコサインを掛けるとX(横)位置
- 半径の長さrとサインを掛けるとY(縦)位置
※参考:【p5.js】Generative Design with p5.js「形 P_2_0_01」のコードを読み解く - クモのようにコツコツと
vertex()は「色 P_1_0_03」にも出てきた。頂点を定めるメソッド。
※参考:【p5.js】Generative Design with p5.js「色 P_1_0_03」のコードを読み解く - クモのようにコツコツと
この頂点をfor文でcircleResolutionの回数繰り返して描画する。
keyReleased()の中身
キーが離れた時の処理
function keyReleased() { if (keyCode == DELETE || keyCode == BACKSPACE) background(255); if (key == 's' || key == 'S') saveCanvas(gd.timestamp(), 'png'); }
- もし
DELETEまたはBACKSPACEを押したら背景をRGB共255に - もし
sまたはSキーを押したらキャンバスをpng画像で保存する
DELETEまたはBACKSPACEを押すとこれまで描画された図形がなくなりリセットされる。
画像の保存設定はいつもの内容。
※参考:【ビジュアルコーディング】p5.jsを習得するためにやった事 まとめ(随時更新) - Qiita
形 P_2_0_03
その次の「形 P_2_0_02」も似た内容なので一緒に見る。
完成品
形 P_2_0_02
先程の図形描画で、1〜3のキーを押すと色が変わる。
JSコード全体
// P_2_0_03 // // Generative Gestaltung – Creative Coding im Web // ISBN: 978-3-87439-902-9, First Edition, Hermann Schmidt, Mainz, 2018 // Benedikt Groß, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni // with contributions by Joey Lee and Niels Poldervaart // Copyright 2018 // // http://www.generative-gestaltung.de // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * drawing with a changing shape by draging the mouse. * * MOUSE * position x : length * position y : thickness and number of lines * drag : draw * * KEYS * 1-3 : stroke color * del, backspace : erase * s : save png */ 'use strict'; var strokeColor; function setup() { createCanvas(720, 720); colorMode(HSB, 360, 100, 100, 100); noFill(); strokeWeight(2); strokeColor = color(0, 10); } function draw() { if (mouseIsPressed && mouseButton == LEFT) { push(); translate(width / 2, height / 2); var circleResolution = int(map(mouseY + 100, 0, height, 2, 10)); var radius = mouseX - width / 2; var angle = TAU / circleResolution; stroke(strokeColor); beginShape(); for (var i = 0; i <= circleResolution; i++) { var x = cos(angle * i) * radius; var y = sin(angle * i) * radius; vertex(x, y); } endShape(); pop(); } } function keyReleased() { if (keyCode == DELETE || keyCode == BACKSPACE) background(0, 0, 100); if (key == 's' || key == 'S') saveCanvas(gd.timestamp(), 'png'); if (key == '1') strokeColor = color(0, 10); if (key == '2') strokeColor = color(192, 100, 64, 10); if (key == '3') strokeColor = color(52, 100, 71, 10); }
概要部分の訳
マウスをドラッグして、形を変えながら描画します。
マウス 位置x:長さ 位置y:太さと線の数 ドラッグ:描画
キー 1-3:ストロークの色 del、backspace:消去 s:pngを保存
以下、「形 P_2_0_02」と違う部分を見ていく
変数strokeColor
冒頭で変数strokeColorを定義
var strokeColor;
値はまだない。
setup()の変更点
次、setup()関数
function setup() { createCanvas(720, 720); colorMode(HSB, 360, 100, 100, 100); noFill(); strokeWeight(2); strokeColor = color(0, 10); }
colorMode()でカラーモード設定。HSBでHが360、Sが100、Bが100、不透明度100strokeColor()にcolor()で線の色を設定。第1引数は0、第2引数は10
colorMode()の第4引数は不透明度
colorMode(mode, max1, max2, max3, [maxA])
maxA Number: range for the alpha (Optional)
color()は引数が二つの場合はstroke()と同じでグレースケールと透明度。
color(gray, [alpha])
「形 P_2_0_02」にあったbackground()とstroke()は削除。
draw()関数の変更点
stroke()が追加されている
function draw() { if (mouseIsPressed && mouseButton == LEFT) { // 中略 stroke(strokeColor); // 中略 } }
stroke()の引数をstrokeColorに
strokeColorは何もしないとsetup()関数の初期値になっている。変更設定は次のkeyReleased()にある。
keyReleased()の変更点
function keyReleased() { if (keyCode == DELETE || keyCode == BACKSPACE) background(0, 0, 100); if (key == 's' || key == 'S') saveCanvas(gd.timestamp(), 'png'); if (key == '1') strokeColor = color(0, 10); if (key == '2') strokeColor = color(192, 100, 64, 10); if (key == '3') strokeColor = color(52, 100, 71, 10); }
- もし
DELETEまたはBACKSPACEを押したら背景のH0、S0、B100に - もし
sまたはSキーを押したらキャンバスをpng画像で保存する - もし
1を押したらstrokeColorのcolor()をグレースケール0、不透明度10%に - もし
2を押したらstrokeColorのcolor()をH192、S100、B64、不透明度10%に - もし
3を押したらstrokeColorのcolor()をH52、S100、B71、不透明度10%に
ここでキーボードの1〜3を押した時にstrokeColorの色を変更する設定が書かれている。それがdraw()関数に反映される。
最後に

ということで形編、今回は2つ見ていきました。形編は数が多いですが、今後も似ている事例は同時に見ることができそうです。
メソッドや三角関数も過去に出てきたものが結構あって、まだ見た瞬間には理解できないがとにかく数多く見ていって、コードに慣れていきたいと思います。それではまた!!
※p5.jsを習得するためにやったことまとめ
【ビジュアルコーディング】p5.jsを習得するためにやった事 まとめ(随時更新) - Qiita
*1:似た内容だったので同時に行けた