p5.js 関数リファレンスと作例:erase()

2023年3月28日火曜日

p5.js リファレンス

t f B! P L

様々な関数の使い方をおさらいし、作例コードを書くことで、自身の知識の定着を図っています。

今回は erase() 関数の解説とサンプルコードを書いて、その使い方を学びます。誤りや、勘違いがあるかもしれません。何かあれば、ご指摘をいただけると嬉しいです。

p5.js は、バージョン 1.6.0 を使用しています。

 

erase() 関数の説明と使い方

erase() | p5.js 公式リファレンス

説明

erase() の後に続く描画は、キャンバスを切り取ることになります。例えば、rect() で描画すると、通常四角形が描かれますが、erase() の後の rect() はキャンバスを四角く切り取ります。

切り取った部分からは下のレイヤーが見えます。createGraphics() で生成するレイヤーと組み合わせると面白い効果を作れるでしょう。


erase() の効果は、noErase() が出てくるまで続きます。


fill(96);
rect(30, 10, 50, 20); // 描画
erase();
rect(10, 20, 40, 50); // 切り取り
noErase();
rect(30, 60, 50, 20); // 描画


erase() と noErase() の間にある rect() や circle() では切り取りが行われますが、background() と image() では切り取りは行われず、通常の描画が行われます。

 

書き方

erase([fillの強さ], [strokeの強さ])

パラメータ

fillの強さ:描画時の fill() に相当する部分の切り取りの強さを 0 から 255 の数値で指定します。0 は全く切り取らず、255 は完全に切り取ります。中間の値は半透明をイメージしてもらえるとよいかと思います。何も指定しない場合のデフォルト値は 255 です。

strokeの強さ:描画時の stroke() に相当する部分の切り取りの強さを指定します。値の考え方は fillの強さ と同様です。

 

fillの強さが半端な、いわゆる半透明の切り取りを重ねるとどうなるか?こうなります。


bd.erase(128);
bd.rect(10, 10, 100, 50);
bd.rect(70, 30, 100, 50);
bd.noErase();

重なった部分の透明度が高くなったような効果が出ていますね。


fillの強さの値を途中で変えたい場合は、一旦 noErase() でリセットしないと反映されないようです。


bd.erase(128);
bd.rect(10, 10, 100, 50);
bd.noErase();
bd.erase(255);
bd.rect(70, 30, 100, 50);
bd.noErase();


noErase() でリセットしないとこうなります。


bd.erase(128);
bd.rect(10, 10, 100, 50);
// bd.noErase();
bd.erase(255);
bd.rect(70, 30, 100, 50);
bd.noErase();


 

返り値

ありません。

 

p5.js 公式リファレンスのコード例の補足


background(100, 100, 250);
fill(250, 100, 100);
rect(20, 20, 60, 60);
erase();
ellipse(25, 30, 30);
noErase();

ellipse() が切り取り扱いになります。レイヤーは一つだけなので、切り取ったところからは Webページの地の色が見えています。



background(150, 250, 150);
fill(100, 100, 250);
rect(20, 20, 60, 60);
strokeWeight(5);
erase(150, 255);
triangle(50, 10, 70, 50, 90, 10);
noErase();

stroke幅を 5 に指定した triangle() が切り取り扱いになります。切り取りは fill 部分が弱め、stroke 部分は完全に切り取る指定のため、三角形の内側が半透明の白のようになっています。



function setup() {
  smooth();
  createCanvas(100, 100, WEBGL);
  // Make a <p> element and put it behind the canvas
  let p = createP('I am a dom element');
  p.center();
  p.style('font-size', '20px');
  p.style('text-align', 'center');
  p.style('z-index', '-9999');
}

function draw() {
  background(250, 250, 150);
  fill(15, 195, 185);
  noStroke();
  sphere(30);
  erase();
  rotateY(frameCount * 0.02);
  translate(0, 0, 40);
  torus(15, 5);
  noErase();
}

「このぐるぐる回っているトーラス部分から、裏にある 'I am a dom element' の文字が見えるでしょ?」という趣向だと思うんですが、実行してみて文字は見えますでしょうか?

私の環境だと、p5.js のバージョンが 1.6.0 では文字は見えず、0.10.2 のときには以下のように文字が見えました。

トーラス部分からその下にある文字が見える

参考までに、ver 1.0.0 だとこうなりました。

トーラス部分だけでなく、球体も透けて下にある文字が見えている

 

erase() を使った作例

erase() を使ったアニメーションの作例を作りました。createGraphics() で生成したレイヤーに erase() で規則的な間隔で穴を開け、それを2枚重ねてモアレを描きます。



/** 
 * p5.js erase() 関数の作例
 * 2枚の穴あき板を重ねてモアレ
 * 
 * @author @deconbatch
 * @version 0.1
 * @license CC0
 * p5.js 1.6.0
 * created 2023.03.27
 */

const w = 480;
const h = w;
const cNum = 20;
const frmRate = 24;
const cycleSec = 4;
const frmCycle = frmRate * cycleSec;
let bd;

function setup() {
  createCanvas(w, h);
  frameRate(frmRate);

  // 板の生成
  bd = createGraphics(w * 0.7, h * 0.7);
  bd.background(0);
  bd.noStroke();
  // 板に穴を開ける
  const cSiz = bd.width * 0.6 / cNum;
  bd.translate(bd.width / cNum * 0.5, bd.width / cNum * 0.25);
  bd.erase();
  for (let ix = 0; ix < cNum; ix++) {
    for (let iy = 0; iy < cNum; iy++) {
      let x = ix * bd.width / cNum;
      let y = (iy + (ix % 2) * 0.5) * bd.height / cNum;
      bd.circle(x, y, cSiz);
    }
  }
  bd.noErase();
}

function draw() {
  imageMode(CENTER);
  translate(w * 0.5, h * 0.5);
  background(255);

  // 固定の板
  image(bd, 0, 0);
  // 回転する板
  rotate(PI * (frameCount % frmCycle) / frmCycle);
  image(bd, 0, 0);
}

erase() の強さをランダムにしてチラチラさせたり。


さらに、大きな円でくり抜いたもう一枚別のレイヤーを被せることで、球のような見た目を作っても面白いです。

 

QooQ