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共に#255
stroke()
でグレースケールを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:似た内容だったので同時に行けた