Vue3 Composition API + TypeScriptでp5.jsを動かす

## これはなに
タイトル通りの環境をさくさくと作っていこうというものです。
ProcessingのJavaScriptライブラリ、p5.jsに手を出してみようと思ったのでVue.jsで環境を作ることにしました。

TypeScriptは必須ではないですが、ライブラリを使用する際は補完が強力なので追加します。

```
"vue": "^3.0.0"
"eslint": "^6.7.2"
"prettier": "^2.2.1"
"p5: 1.4.0"
"typescript": "~4.1.5"
"@types/p5: 1.3.1
```


## Vue CLIで環境を構築する

まずvue cliのバージョンを上げます。

```
yarn global add @vue/cli

vue -V
@vue/cli 4.5.13
```

CLIの設定でVueの3系を選択。
Linter, TypeScriptにチェック。
このへんの解説は下の記事が詳しいです。
https://qiita.com/Junpei_Takagi/items/603d44f7885bd6519de2

### prettierの設定
自動フォーマットを有効にしたいのでprettierの設定をします。

https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
をインストールし、settings.jsonに下記を記述する。

```
{
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },

  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}
```

これでsave時に自動フォーマットが機能します。

## routerの設定

今回はvue routerを使用しているので、不要なrouteを削除します。
またIndex.vueを作成したのでそれを適用させます。

今までコンポーネントをimportしてそれをcomponent要素に充てていたのですが、
関数に置き換えてroute単位で読み込めるみたい。


```javascript
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    name: "Index",
    component: () => import("../views/Index.vue"),
  },
];

const router = createRouter({
  history: createWebHashHistory(),
  routes,
});

export default router;
```

## p5.jsをインストール
```
yarn add p5
```
型も追加

```
yarn add @types/p5
```

## 描画する
ソースコードは[Generative Design with p5.js](https://www.amazon.co.jp/Generative-Design-p5-js-p5-js%E7%89%88%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%A9%E3%83%86%E3%82%A3%E3%83%96%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3-%E2%80%95%E3%82%A6%E3%82%A7%E3%83%96%E3%81%A7%E3%81%AE%E3%82%AF%E3%83%AA%E3%82%A8%E3%82%A4%E3%83%86%E3%82%A3%E3%83%96%E3%83%BB%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0/dp/4802510977/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=3CE8IWY4Q2ESI&keywords=generative+design+with+p5.js&qid=1636868320&sprefix=generative+desi%2Caps%2C254&sr=8-1)を参考にし、それをVueで動くように修正したものです。
またp5.jsの各関数の動きについてはコード内のコメントをご覧ください。

```vuejs
<template>
  <p>Y座標: {{ positionY }}</p>
  <p>X座標: {{ positionX }}</p>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
import p5 from "p5";

export default defineComponent({
  name: "Index",
  setup() {
    const positionY = ref(0);
    const positionX = ref(0);

    const sketch = (p: p5) => {
      p.setup = () => {
        p.createCanvas(720, 720);
        // カラーモデルをHSBに
        p.colorMode(p.HSB, 360, 100, 100);
        // 矩形を描画方法を指定する
        p.rectMode(p.CENTER);
        // 矩形の枠線を隠す
        p.noStroke();
      };

      p.draw = () => {
        positionY.value = p.mouseY;
        positionX.value = p.mouseX;

        // 背景色を現在のカラーモードで指定
        // 色相、再度、明度
        p.background(p.mouseY / 2, 100, 100);
        // 図形の色を現在のカラーモードで指定
        // 背景の反転色を表現する
        p.fill(360 - p.mouseY / 2, 100, 100);
        // 図形の描画（1px ~ 720pxの間で大きさが変わる）
        // X座標, Y座標, width, height
        p.rect(360, 360, p.mouseX + 1, p.mouseX + 1);
      };
    };

    new p5(sketch);

    return {
      positionY,
      positionX,
    };
  },
});
</script>

```

### vueとp5.jsの準備

```javascript
import { defineComponent, ref } from "vue";
import p5 from "p5";
```
Composition APIを使用するためのdefineComponentと、
マウス座標を画面に表示するためrefを。
そしてp5をimportします。

### マウス座標を参照するrefオブジェクトを用意

```javascript
const positionY = ref(0);
const positionX = ref(0);
```
座標を画面に表示するためのrefオブジェクトを用意します。

### 描画前の準備
```javascript
p.setup = () => {
  p.createCanvas(720, 720);
  // カラーモデルをHSBに
  p.colorMode(p.HSB, 360, 100, 100);
  // 矩形を描画方法を指定する
  p.rectMode(p.CENTER);
  // 矩形の枠線を隠す
  p.noStroke();
};
```

p5が持つsetup関数で描画前の準備を定義します。

### 描画
```javascript
p.draw = () => {
  positionY.value = p.mouseY;
  positionX.value = p.mouseX;

  // 背景色を現在のカラーモードで指定
  // 色相、再度、明度
  p.background(p.mouseY / 2, 100, 100);
  // 図形の色を現在のカラーモードで指定
  // 背景の反転色を表現する
  p.fill(360 - p.mouseY / 2, 100, 100);
  // 図形の描画（1px ~ 720pxの間で大きさが変わる）
  // X座標, Y座標, width, height
  p.rect(360, 360, p.mouseX + 1, p.mouseX + 1);
};  
```
draw関数で図形を描画します。
このdraw関数は1秒間に60回レンダリングを行い、
背景色や物体のカラーがレンダリング時のマウス座標で変化します。

### p5をnewする
```javascript
new p5(sketch);
```
setupとdrawを持つsketch関数を引数にとり、new。

### 座標の表示
```vuejs
<template>
  <p>Y座標: {{ positionY }}</p>
  <p>X座標: {{ positionX }}</p>
</template>
```

setup関数でreturnしたrefオブジェクトをtemplateタグ内に置きます。

## 実行
マウスの位置が変わることで、背景と矩形の色が変わる状態を描画できました。

![p5.js test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358229/b3975ed4-66c2-9227-aa6c-3c2a66bca71a.gif)