WEBその他

[p5.js] アニメーションを p5.js + TypeScript + Next.js で作ってみた

WEB
この記事は約8分で読めます。

半澤と申します!

個人的にデザインを調べていた時にp5.jsというアニメーションを作れるJavaScriptのライブラリを見つけたので触ってみた記録を残します。

アプリ作成

ターミナルを起動し、作成するディレクトリに移動して以下のコマンドを入力する。

「sample-app」の部分はプロジェクト名なのでご自由に。設定はよしなに。

yarn create next-app sample-app --typescript

? Would you like to use ESLint with this project? › Yes
? Would you like to use `src/` directory with this project? › Yes
? Would you like to use experimental `app/` directory with this project? … No
? What import alias would you like configured? › @/*

p5.js導入

こちらの記事を参考に導入します。

p5.js×Next.js×TypeScriptを動かしてみる - Qiita
研究やもらったお仕事でNext.jsを使うことは数年前から多々あったのですが、なかなか書けるネタもなくここまで来てしまいました。最近記事書いてないなぁというのもあり、ここいらでNext.jsに関す…

作成したプロジェクトをVSCordで開き、ターミナルから以下のコマンドを実行する。

yarn add react-p5

個人的にコンポーネントで管理したいのでsrc/components/p5.tsxを作成し、ソースを書いていきます。

関数の簡単な説明をコメントで書いておきます。

src/components/p5.tsx

import dynamic from "next/dynamic";
import p5Types from "p5";

const Sketch = dynamic(import('react-p5'), {
    loading: () => null,
    ssr: false
})

export const p5 = () => {
    // 画像などのロードを行う
    const preload = (p5: p5Types) => {
    };

    // 初期処理
    const setup = (p5: p5Types, canvasParentRef: Element) => {
        // 背景の大きさ設定
        // 画面サイズに合わせるようにしている
        p5.createCanvas(p5.windowWidth, p5.windowHeight);
        
        // 背景色設定
        p5.background(0);
        
        // オブジェクトの設置
        // キャンバス内の中心に100pxの丸を表示する
        p5.ellipse(p5.windowWidth / 2, p5.windowHeight / 2, 100)

        // オブジェクトの色設定
        p5.fill(255, 255 , 0);
    };

    // 1フレームごとの処理
    const draw = (p5: p5Types) => {
    };

    // コンポーネントのレスポンシブ化
    const windowResized = (p5: p5Types) => {
        p5.resizeCanvas(p5.windowWidth, p5.windowHeight);
    };

    return (
        <Sketch
            preload={preload}
            setup={setup}
            draw={draw}
            windowResized={windowResized}
        />
    );
};

色についての引数は…

  • 1つの場合:グレースケール 0 が黒で 255 が白
  • 2つの場合:グレースケール + 不透明度
  • 3つの場合:RGB指定(例:255, 255, 255)
  • 4つの場合:RGB + 不透明度
  • カラーコードでも指定可能(background(“#000000”))

t5.tsxの表示確認をするので以下のファイルの内容を変更する。

src/pages/index.tsx

import { Inter } from 'next/font/google'
import { p5 } from '@/components/p5'

const inter = Inter({ subsets: ['latin'] })

export default function Home() {
  const p5Element = p5();
  return (
    <>
      {p5Element}
    </>
  )
}

ターミナルで以下のコマンドを入力する。

yarn dev

このように表示されていたらOK!

チュートリアル

調べてみるといろいろ例を公開していただいている。

examples | p5.js
p5.js a JS client-side library for creating graphic and interactive experiences, based on the core principles of Processing.
Generative Design with p5.js[p5.js版ジェネラティブデザイン] ―ウェブでのクリエイティブ・コーディング
Generative Design, Creative Coding on the Web

一つ試してみる。

p5.js Web Editor
A web editor for p5.js, a JavaScript library with the goal of making coding accessible to artists, designers, educators, and beginners.

ソースはこんな感じになりました。

src/components/t5.tsx

import dynamic from "next/dynamic";
import p5Types from "p5";

const Sketch = dynamic(import('react-p5'), {
    loading: () => null,
    ssr: false
})

export const p5_2 = () => {
    // 画像などのロードを行う
    const preload = (p5: p5Types) => {
    };

    // 初期処理
    const setup = (p5: p5Types, canvasParentRef: Element) => {
        p5.createCanvas(720, 720);
        p5.noFill();
        p5.background(255);
        p5.strokeWeight(2);
        p5.stroke(0, 25);
    };

    // 1フレームごとの処理
    const draw = (p5: p5Types) => {
        if (p5.mouseIsPressed && p5.mouseButton == p5.LEFT) {
            p5.push();
            p5.translate(p5.width / 2, p5.height / 2);
        
            var circleResolution = p5.int(p5.map(p5.mouseY + 100, 0, p5.height, 2, 10));
            var radius = p5.mouseX - p5.width / 2;
            var angle = p5.TAU / circleResolution;
        
            p5.beginShape();
            for (var i = 0; i <= circleResolution; i++) {
              var x = p5.cos(angle * i) * radius;
              var y = p5.sin(angle * i) * radius;
                p5.vertex(x, y);
            }
            p5.endShape();
        
            p5.pop();
        }
    };

    // コンポーネントのレスポンシブ化
    const windowResized = (p5: p5Types) => {
        p5.resizeCanvas(p5.windowWidth, p5.windowHeight);
    };

    return (
        <Sketch
            preload={preload}
            setup={setup}
            draw={draw}
            windowResized={windowResized}
        />
    );
};

まとめ

このように色々なアニメーションを作ることができるp5.js君でした。

ですが、ここまで調べておきながら案件で使用されているところを見たことないです。

理由を調べてみましたがはっきりとしてものが出てこなかったですが、jsよりcssとかでアニメーションを実装した方が処理が軽いし学習コストが低いのではないかと憶測しました。

まだあまり調べてませんが、p5.jsで作ったアニメーションをCCapture.jsというものを使えばgifやpng形式で保存できるみたい…

いつかバックエンドの重い処理を走らせている間とかに、ゲームのロード画面みたいに待ち時間が苦じゃないアニメーションを作ってみたいと思います。