株式会社NiMiLのロゴ

p5.jsをReact+Typescriptのコンポーネント内で扱う

公開 2021/3/1:更新 2021/3/8
アイキャッチ画像

やりたいこと

Reactとp5.jsをいい感じに連携する

Reactのインストール

まず、React+Typescript環境を準備します。

npx create-react-app p5-react --template typescript

cd p5-react

yarn start

これでReactのプロジェクト作成は完了しました!次はp5.jsをインストールしていきます。

p5.jsのインストール

yarn add p5 @types/p5

これでp5.jsのインストールは完了です!次はコンポーネントを作成していきます。

Squareコンポーネントの作成

Square.tsxを作成します。

// src/Square.tsx

import React, { useEffect } from 'react';
import p5 from 'p5';

const sketch = (p: p5) => {
    p.setup = () => {
    	// キャンバスを作成して#squareの子に配置する
        p.createCanvas(p.windowWidth / 2, p.windowHeight / 2).parent('square')
    }

    p.draw = () => {
        p.clear()
        for (let i = 0; i < 3; i++) {
            p.square(10 + (i * 100), 10, 100)
        }
    }
}

const Square: React.FC = () => {

    useEffect(() => {
        new p5(sketch)
    }, [])

    return (
    	// idをsquareに指定する
        <div id="square"/>
    );
}

export default Square;

App.tsxでimportします。

// src/App.tsx

import React from 'react';
import './App.css';
import Square from "./Square";

function App() {
    return (
        <div className="App">
            <Square/>
        </div>
    );
}

export default App;

重要なのがp5のキャンバスを入れたい親要素にidを指定することです!!

親要素にidを指定してcreateCanvas時に.parent('square')メソッドを実行しなければ以下のようなHTMLが吐き出されます。

<html>
    <head>
    :
    </head>
    <body>
        <div id="root">
            <div class="App">
                <div id="square"></div>
            </div>
        </div>
        :
        <main>
        	<canvas id="defaultCanvas0" class="p5Canvas" width="1920" height="944" style="width: 1920px; height: 944px;"></canvas>
        </main>
    </body>
</html>

これではSquareコンポーネントと連携しているとは言えないですね。サンプルのコードの通りに書いていると以下のHTMLが吐き出されます。

<html>
    <head>
    :
    </head>
    <body>
        <div id="root">
            <div class="App">
                <div id="square">
                    <canvas id="defaultCanvas0" class="p5Canvas" width="1920" height="944" style="width: 1920px; height: 944px;"></canvas>
                </div>
            </div>
        </div>
        :
        <main></main>
    </body>
</html>

これでブラウザで確認すると、、

四角形が三つ表示されています!p5.jsをReact+Typescriptのコンポーネントで実行することができました!

Stateの連携

StateはReactのコンポーネント内でしか読み取りも書き込みもできないのでp5.jsと連携するにはコンポーネント外で定義した変数でStateを管理してp5.jsとReactコンポーネントを連携します。

// src/Square.tsx

import React, { useEffect, useState } from 'react';
import p5 from 'p5';

// 連携のための四角形の個数を入れる変数を定義だけしておく
let quantityState: number

const sketch = (p: p5) => {
    p.setup = () => {
        p.createCanvas(p.windowWidth / 2, p.windowHeight / 2).parent('square')
    }

    p.draw = () => {
        p.clear()
        // quantityState分四角形を表示させる
        for (let i = 0; i < quantityState; i++) {
            p.square(10 + (i * 100), 10, 100)
        }
    }
}

const Square: React.FC = () => {
    // React部分でuseStateする
    const [quantity, setQuantity] = useState(3)

    // 連携のための四角形の個数を入れる変数にStateが変わるたびに代入する
    quantityState = quantity

    useEffect(() => {
        new p5(sketch)
    }, [])

    return (
        <div>
            <div id="square"/>
            // Stateを変更するボタン
            <button onClick={() => setQuantity(quantity - 1)}>減らす</button>
            <button onClick={() => setQuantity(quantity + 1)}>増やす</button>
        </div>
    );
}

export default Square;

これでp5.jsとReactコンポーネントの連携も完了です。ブラウザで確認します。

うまく動いていますね!連携も完了です!

これで解説を終わります。ありがとうございました。

ソースコードはこちらに置いてます。

CATEGORIES

分類は、世界の見方

TAGS

記憶の糸をたぐりましょう
twitter icon
instagram icon
友だち追加
twitter iconinstagram icon友だち追加