p5.js の createGraphics() は、公式リファレンスの説明内で「an off-screen graphics buffer」という表現を使って書かれているとおり、描画データを保持する不可視のバッファのようなものです。
その createGraphics() 周りの話について以下のような流れがあって、「もしかして、簡単に表示できる設定にできるのでは?」と思って試したのが、今回の主な内容です。
- createGraphics() を活用した試行錯誤をする中で、コンソールに中身を出力してみていた時に「style の display が none になっている canvas要素」が含まれていた
- 公式の createCanvas() のリファレンスに以下の記載(赤い下線を引いた部分)があった
●reference | https://p5js.org/reference/#/p5/createCanvas
結果
「style の display が none になっているのを無効化」することで、画面上に表示させることができました。
以下は p5.js Web Editor上で処理を実行した時の結果で、画像の右半分の部分を見ると 2つの描画領域が縦並びで表示されているのが分かります。
上記の画像の左半分に書かれた JavaScript のプログラムは以下のとおりです。
let pg;
function setup() {
createCanvas(250, 150);
pg = createGraphics(width, height);
pg.style("display", "");
}
function draw() {
background(100);
pg.background(200);
pg.circle(pg.width / 2, pg.height / 2, pg.height / 2);
}
2つの描画領域を重ねてみる
2つの描画領域を重ねて表示するのを試してみました。
JavaScript のプログラムは以下のとおりです。
let pg;
function setup() {
createCanvas(250, 150);
pg = createGraphics(width, height);
pg.style("display", "");
pg.position(10, 10)
}
function draw() {
background(100);
pg.clear();
pg.background(200, 255*0.5);
pg.circle(pg.width / 2, pg.height / 2, pg.height / 2);
}
createGraphics() で作った描画領域にフィルターをかけてみる
通常、createGraphics() で作成した不可視の描画領域に適用して活用するのはできない、レンダリング時に適用がされるフィルターをかけてみます。
ブラーフィルターでぼかしてみたところ、createGraphics() で作った描画領域にフィルターを適用できたのが確認できました。
JavaScript のプログラムは以下のとおりです。
let pg;
function setup() {
createCanvas(250, 150);
pg = createGraphics(width, height);
pg.style("display", "");
pg.position(50, 50)
pg.style("filter", "blur(15px)");
}
function draw() {
background(100);
pg.background(200);
pg.circle(pg.width / 2, pg.height / 2, pg.height / 2);
}
明示的なリセットが必要な話
※ 以下の話は、createGraphics() で作成した描画領域を不可視のままで使う時にも適用される話です
今回、createGraphics() で作成した不可視の描画領域を、表示可能な描画領域として使ってみましたが、通常のキャンバスと挙動が異なる部分があるので、それを補足しておきます。
公式リファレンスで p5.Graphics について書かれたページを見ると、「Transform」と「Lights」のカテゴリの処理は、自動でリセットされないという話が書いてあります。
ちなみに、通常のキャンバスに対する処理を draw() の中で行った場合、draw() の処理が繰り返される途中で自動でリセットがかかります。
「Transform」カテゴリの「translate()」を使って、この話を確かめてみます。
試しに作った JavaScript のプログラムは以下のとおりで、「draw()」の中で「translate()」を 2箇所で利用しています。一方はキャンバスに対して、他方は createGraphics() で作成した描画領域に対して利用しています。
そして、createGraphics() で作成した描画領域に対してのみ明示的なリセットの処理(「 pg.reset()
」の部分)を加えています。プログラムをそのままで実行してみたり、そのリセットの処理の行をコメントアウトして実行してみたりすると、 createGraphics() で作成した描画領域での「translate()」のリセットの有無の違いが分かります。
※ 繰り返しになりますが、createGraphics() が見えない、描画データを保持する不可視のバッファとして使う場合でも、同じことが起こります。
let pg;
function setup() {
createCanvas(250, 150);
pg = createGraphics(width, height);
pg.style("display", "");
}
function draw() {
background(100);
translate(width / 3, height / 3)
circle(0, 0, height / 2);
pg.reset()
pg.background(200);
pg.translate(width / 3, height / 3)
pg.circle(0, 0, pg.height / 2);
}
自分が過去に createGraphics() と translate() を組み合わせて利用した時、この自動リセットがされないという現象に出くわしたことがあったのですが、今回その原因が分かりました。
自動リセットされない処理
最後に出てきた話について、自動でリセットされないという「Transform」と「Lights」のカテゴリの処理について、リファレンスの該当箇所と思われるところを掲載しておきます。