クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【p5.js】クリエイティブコーディングに挑戦(その2)

p5.jsシリーズ、前回、挑戦したドットインストールの「p5.jsクリエイティブコーディング」の続きです。今回は「# 07」以降、「色」と「動き」です。

【目次】

※参考:【p5.js】クリエイティブコーディングに挑戦(その1) - クモのようにコツコツと

前回のおさらい

ドットインストールの「p5.jsクリエイティブコーディング」の動画を見ながら一緒にコーディング。

※参考:https://dotinstall.com/lessons/creativecoding_intro_p5js

「 #06 乱数を使ってみよう」まで進めた。

See the Pen p5.js #6-2 by イイダリョウ (@i_ryo) on CodePen.

均等に並べた球の大きさのサイズをランダムに変更した。

JSコードはこちら

function setup() {
  // 描画領域のセットアップ
  createCanvas(600,200);
  background(0);
  noStroke();
  fill(255);
  
  const step = 20;
  
  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      //const size = random(0, 15);
      let size;
      if(random() < 0.95) {
        size = random(0, 10);
      } else {
        size = step;
      }

      ellipse(x, y,size,size);
  }
}
  
}

詳細は前回の記事を参照。

※参考:【p5.js】クリエイティブコーディングに挑戦(その1) - クモのようにコツコツと

色をランダムに変更する

これまでは黒背景に白い円のみだったが、円の色をランダムに変更する。

※参考: #07 色に応用してみよう

やってみた。

See the Pen p5.js #7-1 by イイダリョウ (@i_ryo) on CodePen.

円の色がランダムに変化!モノクロだがグレーの濃さが変わる。

function setup() {
  // 中略
    
  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      const size = random(0, 15);
      fill(random(255));
      ellipse(x, y,size,size);
  }
}
  
}
  • 二重ループの中、変数sizeは元のrandom()に戻す。引数0〜15。
  • ループの中に色設定のfill()を書く。引数はrandom(255)

ループの中に色設定を書いて引数をrandom(255)にすると0から255の間のグレーになる。

次に、色をフルカラーにする。

See the Pen p5.js #7-2 by イイダリョウ (@i_ryo) on CodePen.

先ほどのランダムな色がフルカラーになった!

function setup() {
  // 中略
  
  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      const size = random(0, 15);
      fill(random(255),random(255),random(255));
      ellipse(x, y,size,size);
  }
}
  
}
  • fill()の引数を3つに増やす。値は同じくrandom(255)

これによって、RGBの数字がそれぞれ0〜255の間のランダムな値になる。

次に、色みを少し整える。

See the Pen p5.js #7-3 by イイダリョウ (@i_ryo) on CodePen.

ランダムな色でありながら全体的には緑系がメインの色みになった。

function setup() {
  // 中略
  
  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      const size = random(0, 15);
      fill(random(200),random(255),random(100));
      ellipse(x, y,size,size);
  }
}
  
}
  • fill()の中のrandom()の色Rを200、Gを255、Bを100にする。

これによってR(赤)は0〜200、G(緑)が0〜255、B(青)が0〜100で緑が一番広い範囲の色になる。

さらに厳密に色みを整える。

See the Pen p5.js #7-4 by イイダリョウ (@i_ryo) on CodePen.

今度は赤っぽくなった。

function setup() {
  // 中薬
  
  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      const size = random(0, 15); 
      const r = random(255);
      const g = random(r);
      const b = random(g);      
      fill(r,g,b);
      ellipse(x, y,size,size);
  }
}
  
}
  • 変数rrondom()でR(赤)の乱数の範囲を255に。
  • 変数grondom()でG(緑)の乱数の範囲をrに。
  • 変数brondom()で B(青)の乱数の範囲をgに。
  • 色設定fill()の引数をrgb

R(赤)は0から255の範囲の乱数になるが、G(緑)はループ時のRの最大値を超えない範囲の乱数になる。さらにB(青)の色はGの最大値を超えない範囲の乱数なのでさらに暗くなる。これによって、全体的に赤の色みが強くなる。

HSB色空間を使う

p5.jsはRGB以外のカラーモードも指定できる。今度はHSB色空間を使う。

※参考: #08 HSB色空間を使ってみよう

なお、HSB色空間についてはこちらの記事を参照。

※参考:【配色】色相環のH値をいろいろ測ってみた(HSB、マンセル、オストワルト、PCCS、Web配色ツール) - クモのようにコツコツと

やってみた。

See the Pen p5.js #8-1 by イイダリョウ (@i_ryo) on CodePen.

ランダムだが青〜紫〜赤紫くらいの色相になっている。

function setup() {
  // 中略
  
  colorMode(HSB, 360, 100, 100);
  
  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      const size = random(0, 15); 
      const h = random(200, 320);
      const s = 100;
      const b = 100;      
      fill(h,s,b);
      ellipse(x, y,size,size);
  }
}
  
}
  • colorMode()でカラーモード設定。第1引数でHSBモードに。第2~4引数で順番に色相(H)、彩度(S)、明度(B)の最大値を設定。Hは角度で360度。他は100。
  • 二重ループの中、変数hで色相設定。random()で0〜15度。変数sと変数bは100。
    色設定fill()には変数hsbを入れる。

これで色相は0〜15度のランダムな値になる。彩度と明度は最大値の100。

上の例は全部の色がくっきりだったので明度にも差異を付けたい。

See the Pen p5.js #8-2 by イイダリョウ (@i_ryo) on CodePen.

function setup() {
  // 中略
  
  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      const size = random(0, 15); 
      const h = random(200, 320);
      const s = 100;
      const b = size * 5;      
      fill(h,s,b);
      ellipse(x, y,size,size);
  }
}
  
}
  • 変数bsize×5に

これで、円のサイズに比例して円が大きいほど明るく、小さいほど暗くなる。sizeは15までのため5倍にしてメリハリを強調している。

動きを加える

色の次は動きを加える。

#09 作品に動きをつけてみよう

最初にユーザーの動きに反応して動く円を加える。

See the Pen p5.js #9-1 by イイダリョウ (@i_ryo) on CodePen.

ユーザーの動きに合わせていくつもの円が描かれる。

function setup() {
  // 描画領域のセットアップ
  createCanvas(600,200);
  background(0);
  noStroke();
  fill(255);
  colorMode(HSB, 360, 100, 100);
}

function draw() {
  const step = 20;
  const size = 5; 

  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      ellipse(x, y,size,size);
  }
}
  
    ellipse(mouseX, mouseY, 20, 20);
    
}
  • setup()メソッドの下にdraw()関数(一定時間ごとに描写を繰り返し行う)を加える
  • 変数sutepと二重ループはdraw()の中に移動。size()はループの外に出し、5に固定。カラー系の設定はいったん削除。
  • ループの外にもう一つ円描画ellipse()を加える。第1〜2引数は位置で、マウスの横位置mouseX、縦位置mouse Y。第3〜4引数はサイズでそれぞれ20。

これで5のサイズで規則的に並んだ円と、それとは別にユーザー操作で現れる20のサイズの円を別々に設定できた。

円の軌道が残り続けるのがうるさいので削除する。

See the Pen p5.js #9-2 by イイダリョウ (@i_ryo) on CodePen.

ふ〜綺麗になった。

function setup() {
  // background(0);をdraw()に移動
 // 中略
}

function draw() {
  background(0);
  // 中略
  }
} 
// 中略  
}
  • background(0);draw()メソッドに移動

これによって背景を黒(0)に都度描画されるため、軌道が消えるようになった。

次に、軌道が完全に消えるのも寂しいので残像が残るような描画に書き換える。

See the Pen p5.js #9-3 by イイダリョウ (@i_ryo) on CodePen.

おお、フワンと消えた!カッコいい♪

function setup() {
  // 中略
  colorMode(HSB, 360, 100, 100, 255);
}

function draw() {
  background(0, 20);
  // 中略
  }
}
// 中略    
}
  • setup()のカラーモードの引数を1つ増やして透明度255を設定。
  • background()の引数を1つに増やし第2引数に透明度20を入れる。

これによって、半透明の黒がだんだんと上に塗り重ねられていくため、円がフワンと消えていくように見える。

マウスとの距離によってサイズ、色を変える

先ほどは背景の繰り返された円とユーザー操作の円は別個の存在だった。今度は背景はなくしてユーザー操作の円をもっと複雑な描画にする。

#10 マウスとの距離を使ってみよう

ユーザー操作の円の設定拡張。

See the Pen p5.js #10-1 by イイダリョウ (@i_ryo) on CodePen.

先ほどより大きい円達の塊が動く!ワイドショーで擦りガラスごしにしゃべってる人みたいな表現。

function setup() {
  // 中略
}

function draw() {
  background(0);
  const step = 20;

  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      const d = dist(x, y, mouseX, mouseY);
      const size = d / 10; 
      ellipse(x, y,size,size);
  }
}
}

draw()メソッドの中を書き換えている。

  • background(0)で背景は真っ黒に
  • ユーザー操作の円のサイズの設定は二重ループの中に
  • 変数ddist()メソッドでマウスとの距離を測る。xymouseXmouseY
  • 変数sizeで円をdを10で割ったサイズに

dist()はp5.jsに用意されたメソッド。

※参考:reference | p5.js

マウスから離れた場所ほど10で割ったサイズに小さくなるループを繰り返す。

次に、三角関数を加えて波紋のような表現にする。

See the Pen p5.js #10-2 by イイダリョウ (@i_ryo) on CodePen.

笑ゥせぇるすまんに「ドーン!」されたような感じw

function setup() {
  // 中略
}

function draw() {
  // 中略

  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      const d = dist(x, y, mouseX, mouseY);
      const size = map(sin(d * 0.05), -1, 1, 0, 10); 
      ellipse(x, y,size,size);
  }
}
}

二重ループの中を書き換えている。

  • 変数sizeを三角関数sin()で引数dの0.05倍にしているが、それをmap()で囲ってマッピング。
    第2〜4引数がマッピングの設定値で。第2〜3引数の-1〜1の範囲を第3〜4引数の0〜10の範囲に置き換えている。

sin()はp5.jsに用意されたメソッドで三角関数のこと。引数はdの0.05倍。

Calculates the sine of an angle. This function takes into account the current angleMode. Values are returned in the range -1 to 1.

※参考:reference | p5.js

翻訳すると「角度のサインを計算します。 この関数は現在のangleModeを考慮に入れます。 値は-1から1の範囲で返されます。」

map()はp5.jsに用意されたメソッドでマッピング。マッピングとは関連付けのこと。

※参考:マッピング

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).

※参考:reference | p5.js

翻訳すると「ある範囲から別の範囲に番号を再マップします。上記の最初の例では、数値25が0から100の範囲の値からウィンドウの左端(0)から右端(幅)までの範囲の値に変換されます。」

sin()の-1から1の範囲をmap()で0〜10の範囲にマッピングしたということ。

最後に、色の設定も行う。

See the Pen p5.js #10-3 by イイダリョウ (@i_ryo) on CodePen.

喪黒福造の「ドーーーン!」から花火のようなキレイな色になった♪

function setup() {
  // 中略
}

function draw() {
  // 中略

  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      const d = dist(x, y, mouseX, mouseY);
      const size = map(sin(d * 0.05), -1, 1, 0, 10); 
      fill(map(sin(d * 0.05), -1, 1, 60, 320), 100, 100)
      ellipse(x, y,size,size);
  }
}   
}

二重ループの中に色設定を追記している。

  • fill()で色設定。第1引数は色相(H)、第2引数は彩度(S)、第3引数は明度(B)。
  • 第1引数で色相設定にもsin()で三角関数を設定。それをmap()でマッピング。 -1〜1の範囲を60〜320の範囲に。
  • 第2〜3引数の彩度と明度は100に固定。

これで、マウスからの距離によって色相が60〜320の角度の間をループする。

最後に

f:id:idr_zz:20190721194227j:plain

ドットインストールのコードをなぞってみて、自分で実現できたのは嬉しかったが、これを自力でゼロから作れたかというとそれはなかなか難しいと思いました。途中途中で横道にそれて書き換えてくれてたので、ここで得た知見をヒントに、自力でゼロからいろいろ作ってみたく思います。

ユーザー操作に反応するインタラクティブコンテンツは自分にとってプログラミングの初期衝動。かつてFLASH職人たちがつくっていたカッコいいコンテンツを自分も作れるようになりたい!その1歩をp5.jsで経験できました。それではまた!

※続き書きました!

www.i-ryo.com


※参考:p5.jsを習得するためにやった事まとめ qiita.com