p5.jsをTypeScriptで書く方法
Table of Contents
p5.jsをTypeScriptで使うセットアップをしてみたので、その流れをまとめてみます。
JavaScript、TypeScriptも業務で扱うものの、環境構築の経験はないので、もっと良い方法があれば書き直す
前提 #
- 作業はChatGPTにアシストしてもらいながら行った
- webpackの設定のためにdev.toのポストとかを参照した
手順 #
- スケッチを書いていくディレクトリを作る
- TypeScriptを使う準備
- ディレクトリに入り、
npm init
を実行する
(実際にはnpm init -y
で色々とスキップした) npm install typescript
を実行するtsconfig.json
を生成するためnpx tsc --init
を実行する
(実際には、ChatGPTが出力したtsconfig.jsonをコピペした)
- ディレクトリに入り、
- p5.jsを使う準備
npm install p5
を実行する- p5.jsの型定義ファイルを使うため
npm install @types/p5
を実行する
- webpackでバンドルする準備
npm install --save-dev webpack webpack-cli ts-loader
を実行するwebpack.config.js
を生成するためnpx webpack init
を実行する
(実際には、ChatGPTが出力したwebpack.config.jsをコピペした)- ホットリロードを有効にするため、
webpack.config.js
にentry
とdevServer
の設定を追加する package.json
のscripts
にwebpack serve --mode development --open
を追加する
- スケッチを表示する
index.html
を作成し、webpackがバンドルしたjsファイルを読み込むようにする
(今回は、ChatGPTが出力したHTMLをほぼそのまま使った) (index.htmlを置く場所は、webpack.config.jsのdevServerにも記載のある dist ディレクトリ)npm run start
を実行する
tsconfig.json #
ChatGPTが出力したものをコピペした。コメントアウトも一緒に出力してくれた。 設定内容の細かいことは分かっていないので、詳細や必要最低限のセットアップがわかったら、随時更新するつもり。
{
"compilerOptions": {
"target": "es6", // 出力するJavaScriptのバージョンを指定
"module": "es6", // モジュールシステムを指定
"strict": true, // 厳格な型チェックを有効にする
"esModuleInterop": true, // ESモジュールとCommonJSの互換性を提供
"forceConsistentCasingInFileNames": true, // ファイル名の大文字小文字の一貫性を強制
"skipLibCheck": true, // 型定義ファイルのチェックをスキップ
"outDir": "./dist", // 出力ディレクトリを指定
"rootDir": "./src", // ソースファイルのルートディレクトリを指定
"moduleResolution": "node", // Node.js のモジュール解決を使用
"allowSyntheticDefaultImports": true, // デフォルトインポートのシンセティックを許可
"allowJs": true,
},
"include": ["src/**/*"], // コンパイル対象のファイルを指定
"exclude": ["node_modules"] // 除外するファイルを指定
}
webpackでも似たようなことを書くので、もしかしたらrootDirやoutDirは不要かもしれない。
webpack.config.js #
こちらは、ChatGPTが出力したものをベースにしつつ、dev.toのポストで見つけたコードを合体した。 細かな設定内容は理解していないので、わかってきたら更新したい。
const path = require('path');
module.exports = {
entry: './src/main.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
devServer: {
static: './dist',
},
};
package.json #
package.jsonは自動生成の部分が大半だけど、全体を載せておく。scripts
のstart
さえあれば良い。
{
"name": "p5practice",
"version": "1.0.0",
"scripts": {
"build": "webpack --mode development",
"watch": "webpack --mode development --watch",
"start": "webpack serve --mode development --open"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"@types/p5": "^1.7.6",
"p5": "^1.10.0",
"typescript": "^5.5.4"
},
"devDependencies": {
"ts-loader": "^9.5.1",
"webpack": "^5.93.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.0.4"
}
}
src/main.ts #
main.tsに、スケッチを実装していく。
TypeScriptでp5.jsを使う場合、p5オブジェクトを経由して処理を呼び出すインスタンスモードで書く方が安全で、Java版やWeb版で見慣れた書き方(p5.jsではグローバルモードと呼ぶ)で書くには工夫が必要のようだった。
インスタンスモードでも見慣れた雰囲気にしたくてsetup
とdraw
の定義と、p5オブジェクトにセットする処理を分けて書いたけど、即時関数や無名関数で直接渡しても大丈夫のはず。
import p5 from 'p5';
const sketch = (p: p5) => {
function setup() {
p.createCanvas(p.windowWidth, p.windowHeight);
};
function draw() {
p.background(255);
p.textSize(20);
p.textAlign('center');
p.text(new Date(), p.width/2, p.height/2);
};
function windowResized(event?: object) {
p.resizeCanvas(p.windowWidth, p.windowHeight, false);
};
p.setup = setup;
p.draw = draw;
p.windowResized = windowResized;
};
new p5(sketch);
index.html #
bundle.jsを読み込むだけ。 bodyが初期スタイルなので、スタイルを直接調整した。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>P5 Project</title>
</head>
<body style="margin: 0px; overflow: hidden;">
<script src="bundle.js"></script>
</body>
</html>
これでとりあえず表示はできるようになった。