前提の話
今年のQiita Conferenceのサイトでは、WebGLを使い背景にアニメーションを施してました。
もともと数学が好きではなく、3Dとかそういったものにも興味はなかったのですが「チーム内でもそういったものをキャッチアップしていこう」という動きもあって、ちょっと触ってみようと思いたった次第です。
P5.jsとは
QiitaにもP5.jsの記事は沢山あるのですが、あえて初めてP5.jsのことを知った人のために紹介をしておきます。
p5.js はクリエイティブ コーディング用の JavaScript ライブラリで、アーティスト、デザイナー、教育者、初心者など、誰もがコーディングにアクセスし、包括的に活用できるようにすることに重点を置いています。p5.js は無料かつオープン ソースです。
ここ数年ではプログラミング初学者、小学生や中学生のプログラミング教材としてP5.jsが使われていることもあるそうです。
P5.jsをはじめるだけなら、ブラウザさえあればオンラインエディタでいきなりコーディングが出来たりします。
WebGLじゃなくてP5.jsなのはなぜ?
アニメーションの実装が、WebGLよりも敷居が低そうと思ったからです。
いきなりハードルが高いと、分からなくなったら高確率で放り投げてしまうので敷居は低いにこしたことは無いです。
セットアップ
今回はReactとP5.jsのセットアップをやっていきます。
create-react-app
が非推奨になり、Next.jsやRemixなどのフレームワークと併用して作成することが推奨されていますが、今回はお試しで使うだけなのでViteとReactで作成していきます。
実行環境
- MacOS Sequoia 15.1.1
- Node 22.12.0
- npm 10.9.0
まずはターミナルを立ち上げて作成のコマンドを入力します。
npm create vite@latest
するとどんな名前のプロジェクトにするか聞かれるので任意の名前にします。
ここではmy-p5js-test
という名前のプロジェクトにします。
? Project name: › my-p5js-test
プロジェクト名を決めたら、今度はどんなフレームワークを使用するか聞かれるので、Reactを選択します。
するとJavaScriptとTypeScriptのどちらか使用するかを聞かれるので、TypeScriptを選択します。
とても分かりづらい画像ですが一番上が「TypeScript」上から二番目が「TypeScript + SWC」になっています。
ちなみにSWCとはVercel社が作成しているBabelの代替えとなるコンパイラーらしく、Babelよりも20倍早いそうです。
これでプロジェクト作成完了です。
Done. Now run:
cd my-p5js-test
npm install
npm run dev
さらにcd my-p5js-test
で移動し、npm install
、npm run dev
の順にコマンドを入力すると以下のようなメッセージが出ます。
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
ブラウザでhttp://localhost:5173/
にアクセスすると初期画面が表示されています。
次にP5.jsを使用するパッケージをインストールします。
npm install p5 @p5-wrapper/react
今回は背景をアニメーションしたいのでBackground.tsx
というファイルを作ります。
そこで、とりあえず動くかどうかを試してみたいので、公式のコードをコピペしてみました。
import { ReactP5Wrapper, P5CanvasInstance } from "@p5-wrapper/react";
function sketch(p5: P5CanvasInstance) {
p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL);
p5.draw = () => {
p5.background(250);
p5.normalMaterial();
p5.push();
p5.rotateZ(p5.frameCount * 0.01);
p5.rotateX(p5.frameCount * 0.01);
p5.rotateY(p5.frameCount * 0.01);
p5.plane(100);
p5.pop();
};
}
export const Background = () => {
return <ReactP5Wrapper sketch={sketch} />;
};
そしてApp.tsx
でimportして表示させてみます。
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import { Background } from "./background/Background"; // インポート
import "./App.css";
function App() {
const [count, setCount] = useState(0);
return (
<>
<div>
<Background /> {/* この位置で表示させてみる */}
<a href='https://vite.dev' target='_blank'>
<img src={viteLogo} className='logo' alt='Vite logo' />
</a>
<a href='https://react.dev' target='_blank'>
<img src={reactLogo} className='logo react' alt='React logo' />
</a>
</div>
<h1>Vite + React</h1>
<div className='card'>
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className='read-the-docs'>
Click on the Vite and React logos to learn more
</p>
</>
);
}
export default App;
どうやら表示できているようです。
一応今回はセットアップのみになります。
参考