🖼️

p5.js開発にて、htmlファイルにcanvasタグを直書きしたくないときの方法

2024/08/27に公開

はじめに

ホームページのポートフォリオに作品を追加しました。

https://fujii-web.works/playground/twisted-scroll-rings

カフェや会社のおしゃれ空間のバックグラウンドムービーをイメージしました。

モチーフは、みんな大好きストロガッツ本の表紙でおなじみ「ねじれストークス波」です。

https://zenn.dev/fww/books/nonlinear-dynamics-and-chaos/viewer/00_summary#おまけ%3A表紙の絵について

本当はこの作品の説明をしたかったのですが、なんか思ってたんと違う感じになっちゃったので、制作の際につまづいた点をメモしておこうと思います。

開発環境

前回ご紹介したようにVite管理のVanilla TypeScriptでp5.jsを書いています。
今回はTailWindCSSは使っていません。

https://zenn.dev/fww/articles/dev_vite-typescript-tailwindcss-p5js-boilerplate

なんでopenprocessing.org使わないの?

や、私もそっちでやってみようと思って、ちょっと使ってみたんですよ。

https://openprocessing.org/sketch/2331663

  • 馴れてないせいか、開発に時間がかかる...(VSCodeに馴れすぎて、ブラウザベースのUIに抵抗が...)
  • TypeScriptが使えない(なんでやねん...)
  • 全画面表示ができない(なんかいらないdom要素が貼られていて気に入らない)

ということで、自前のホームページにポートフォリオページとして公開することとしました...!

WEBGLで3D描画

今回はWEBGLでsetupしました。
perspectiveの設定は適当ですが、視野角は60°で固定。
アスペクト比は、再生画面サイズに応じて自動調整されるように設計しました。

https://p5js.org/reference/p5/perspective/

ソースコード例(html + ts)

※基本的な部分のみを抜き出して掲載しています!

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Twisted Scroll Rings | Fujii Web Works</title>
  </head>
  <body>
    <div id="container">
      <div id="app"></div>
    </div>
    <script type="module" src="/app.ts"></script>
  </body>
</html>
app.ts
import p5 from 'p5';

new p5((p: p5) => {
  // FPS: https://p5js.org/reference/p5/frameRate/
  const fps = 30
  // Field of View: https://en.wikipedia.org/wiki/Field_of_view
  const fovy = Math.PI / 3
  // p5.jsで色を扱うときはcolorオブジェクト便利だよね!: https://p5js.org/reference/p5/color/
  let bg_color = p.color('#FEFAEF')

  p.setup = () => {
    // WEBGLモードで起動
    let canvas = p.createCanvas(p.displayWidth, p.displayHeight, p.WEBGL);
    // 生成されたcanvas要素を取得
    const canvasElement = canvas.elt as HTMLCanvasElement;
    // 'app'要素を取得し、canvas要素を追加
    const appElement = document.getElementById('app');
    if (appElement) {
      appElement.appendChild(canvasElement);
      // フレームレート設定
      p.frameRate(fps);
      // カメラの設定(必要に応じて調整)
      p.perspective(fovy, p.displayWidth / p.displayHeight);
      // おまけ機能: クリックしたら全画面モード切り替え(スマホでは意味無し)
      const mousePressed = () => {
        if (p.mouseX > 0 && p.mouseX < p.displayWidth && p.mouseY > 0 && p.mouseY < p.displayHeight) {
          let fs = p.fullscreen();
          p.fullscreen(!fs);
        }
      }
      canvas.mouseClicked(mousePressed);
    }
  };

  // コーディングがんばって!
  p.draw = () => {
    p.background(bg_color);
  };

  // 自動リサイズ
  window.onresize = () => {
    p.resizeCanvas(p.displayWidth, p.displayHeight);
    p.perspective(fovy, p.displayWidth / p.displayHeight);
  };
});

ポイント1: <id="app" />に<canvas />を入れ込んでいくスタイル

本当は、createCanvasの第4変数にHTMLCanvasElementを指定すれば良いのです...!
が、上記の方がたくさんcanvas作って並べたいときに便利そうなので、こっちで実装しています。

https://p5js.org/reference/p5/createCanvas/

公式に書いてない方法なので、一部ブラウザで不具合が出そうですが、知らん。

ポイント2: 画面サイズにあわせて自動リサイズ機能

スマホをよくちゃかちゃか縦向け横し向けしちゃうので、自分用につけています。

ポイント3: canvasをクリックしたら全画面モード切り替え

PCをスクリーンにつないで、観賞用に映像を流す時、さくっと全画面切り替えができるようにしました。
スマホでは意味無いですが...

おわりに

改めて眺めると、openprocessing.orgで開発されている方からすると、どれも無意味な機能ですね!!
何か参考にしていただけると幸いです!
良いコーディングライフを!!

Discussion