👀

[p5.js] ウインドウをリサイズした時canvasタグが複製されないようにしたい

2024/01/29に公開

やったこと

不思議な現象が起きたのでメモ。

p5.jsを使ったウェブサイトを作成していて画面をリサイズするときにcanvasタグが増殖するバグに遭遇した。
増殖したcanvasタグはすぐさまdisplay:noneが付けられるので見た目的には影響がない。だから放置してもよかったけれど、スクロールでも増殖しちゃうし、リサイズのたびに増殖していけば徐々にサイトが重くなってしまうので色々調べてみた。

リサイズすると謎に増えるcanvasタグ。

そもそもcreateGraphicsを実行するとcanvasタグが一つ増える

createGraphicsの挙動を見ていて知ったことだが、この関数を実行するとcanvasタグが1つ増えてメインのcanvasとp5.Graphicsのcanvasを重ねて見せていたようだった。
実際にここのコードを見てみる。

コードを見てみると確かにcanvasタグを作成している。

resize処理の中にcreateGraphicsを実行すると...

createGraphicsを使ってcanvasタグが増えるということは、resize処理の中にcreateGraphicsを実行してしまうと使われなかったcanvasタグが残り続けてしまう。結果リサイズのたびにcanvasタグが増殖する事態になっていた。

resize処理の中にcreateGraphicsを書かないとどうなるか?

resize処理の中にcreateGraphicsを書かないと今度はp5.Graphicsが最初に作成されたサイズで固定されてしまう。そのため、途中で見切れるといった事態が発生する。

p5.Graphicsのcanvasサイズが更新されないので途中で見えなくなった。

どう回避するか?

p5.elementには中身を初期化するremove関数というものが存在している。最終的には以下のように書いてリサイズ時でもp5.elementのサイズを可変にしつつcanvasタグが複製されないよう調整した。

const sketch = function (p, one) {
  let pg;
  p.setup = () => {
    let canvas = p.createCanvas(
      p.windowWidth,
      window.outerHeight * 0.9,
      p.WEBGL
    );
    pg = p.createGraphics(p.width, p.height);
  };
  
  p.draw = () => {
  // 省略
  }
  p.windowResized = () => {
    p.resizeCanvas(p.windowWidth, window.outerHeight * 0.9, p.WEBGL);
    pg.remove(); // 無限canvas増殖対策
    pg = p.createGraphics(p.width, p.height);
  };

createGraphicsの関数ではcanvasタグもオプションで渡せるのでその方法を使って上書きすることもできそうだと思った。

参考文献

https://github.com/processing/p5.js/issues/2064

https://p5js.org/reference/#/p5.Graphics

https://github.com/processing/p5.js/blob/v1.9.0/src/core/p5.Graphics.js#L10

Discussion