[連載]Reactとp5.jsでクソかっこいいサイトを作ろう！！(part 1)

#はじめに

この記事では以下のような表現をウェブサイト上で実現し,とにかくカッコいいサイトを作ることを目指します.

![名称未設定rus.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386550/f368971b-a58c-4824-733d-11d35c8ac825.gif)



上記のような表現をするときによく用いられるのはProcessingというプログラミング言語, およびProcessingのJavaScriptラッパーであるp5.jsですが,今回はReactを用いてGenerative Artをコンポーネントとして実現します.

p5.jsをReactでそのまま扱うのは大変なので,今回はreact-p5およびreact-p5-wrapperというp5.jsをReactで簡単に扱えるようにしたライブラリを用います.先人に感謝です.

本記事の対象読者は以下の通りです.
- React.jsを少し触ったことがある
- クリエイティブコーディングに興味がある
- Webサイトの表現の限界を追求してみたい


また,環境構築にはcreate-react-appを用い,github-pagesに作成したアプリケーションをデプロイします.

実行環境は以下の通りです.
- macOS Mojave : 10.14.5
- node : 12.7.0
- npm : 6.10.2
- yarn : 1.17.3
- create-react-app : 3.0.1
- github-pages : 2.1.0

今回は初回なので,p5.jsをReact上でどう動作させるのか,といった所に焦点を当てていきます.

では早速やっていきましょう！！

# 環境構築

まず自分の好きなディレクトリから,create-react-appを用いてアプリケーションの雛形を作成します.
yarnやcreate-react-appがない場合は以下のようにインストールできます.

```terminal.
brew install yarn
yarn add create-react-app -g
```

その後プロジェクトディレクトリへ移動してください.
(myappという名前は適宜変更してください)

```terminal.
create-react-app myapp
cd myapp
```


プロジェクト自体を作成できたら,まずはサイトのデプロイ自体ができるかどうかを試してみましょう.
以下のコマンドを入力してください.

```terminal.
yarn add gh-pages --save-dev
```

さらに,プロジェクトディレクトリ直下にあるpackage.jsonに,以下のように書き加えてください.

```package.json
...(省略)
"homepage": "http://username.github.io/myapp"

"scripts": {
...(省略)
  "predeploy": "yarn run build",
  "deploy": "gh-pages -d build --git git"
}
```

上記のように記述することで,コマンドラインにてmyappディレクトリで,`yarn run deploy`といった形で上記のコマンドを実行できるようになります.

自分用便利コマンドみたいな感じですね.

それでは次に,github pages用の準備をしていきます.
github pagesを使うと,静的なサイトに限りますが,簡単にプロトタイプを作って試せるので便利です.

まず,自分のGitHubのページへ飛び,リポジトリを作成してください.
この時の名前は何でもいいですが,`create-react-app`で使った名前と同じ名前がわかりやすいかなと思います.

リポジトリを作成したら,作成直後のページに書いてあるようにremote repositryへのpushまでやってしまいましょう.

多分以下のようなコマンドになると思います(README.md関連のコマンドは省略).

```terminal.
git add -A
git commit -m "first commit"
git remote add origin git@github.com:username/myapp.git
git push -u origin master
```

さらにpackage.jsonに記述したコマンドを動かしてみましょう.

以下のコマンドを実行してください.

```terminal.
yarn run deploy
```

なお,github-pagesへのデプロイ時にエラーが出た際は,deployコマンドに`--git git`オプションが付いているかを確認してみてください.

2019年8月6日現在, github-pages 2.1.0でデプロイをする際にエラーが発生してしまうバグがあるようです(以下のような感じです).

詳しくは拙文ですが以下をご覧ください.
[gh-pages -d buildが出来ない(キレそう)](https://qiita.com/hppRC/items/ae09fde93914c43dc273)

うまくデプロイができると, [https://username.github.io/myapp/](https://username.github.io/myapp/)にてcreate-react-appによって生成された画面が確認できると思います.

ひとまずこれでデプロイの確認は完了ですね.

# react-p5-wrapperを試してみる
改めてp5.jsの説明からいきます.
p5.jsとは,Javaベースのビジュアルアート・デザイン用の言語・開発環境であるprocessingのJavaScriptラッパーです.

processing経験者なら簡単に移行できるよう,構文などもほとんど同じで書かれているらしいです(筆者はprocessingを触ったことがないのであまり言及できません)

今回用いるのは,Reactのコンポーネント指向な考え方に合うように作られた,p5.jsのラッパーライブラリ,react-p5-wrapperです.

このライブラリを用いることで,簡単に動的な描画アートの変更や,アプリケーションの状態による挙動の変化などを実現することができます.

まず以下のように必要なモジュールをインストールしてください.

```terminal.
yarn add react-p5 --save
yarn add react-p5-wrapper --save
yarn upgrade p5@0.9.0 --save
yarn add styled-components --save
yarn add styled-reset --save
yarn add react-router-dom --save
```

さらに,create-react-appで生成されたファイルをいじっていきます.
ディレクトリ構成は以下のようになる予定なので,適宜参照してください.

```
.
├── README.md
├── build
├── package-lock.json
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── src
│   ├── App.css
│   ├── App.js
│   ├── index.css
│   ├── index.js
│   ├── serviceWorker.js
│   └── testSketch.js
└── yarn.lock
```

では,まずsrcディレクトリのApp.jsファイルをいじっていきます.

```src/App.js
import React from 'react'
import P5Wrapper from 'react-p5-wrapper'
import testSketch from './testSketch'
import './App.css'

const App = () => (
   <P5Wrapper sketch={testSketch} />
)

export default App
```
上記の通り,react-p5-wrapperモジュールをimportして,Appコンポーネントの中でP5Wrapperコンポーネントを呼び出しています.

P5Wrapperコンポーネントにはsketchという関数オブジェクトを渡します.
sketchがビジュアルアートのための関数で,作品の本体になります.

では,作品を作っていきましょう.

まずはreact-p5-wrapper公式のテストコードを動かしてみることとします.

以下は記載されているコード例をES6記法で書き直したものです.
srcディレクトリ以下にtestSketch.jsファイルを作成して記述していきます.

```src/testSketch.js
const testSketch = (p) => {
    let rotation = 0

    //初期設定
    p.setup = () => {
      p.createCanvas(p.windowWidth, p.windowHeight, p.WEBGL)
    }

    //P5Wrapperコンポーネントからのpropsの受け渡し
    p.myCustomRedrawAccordingToNewPropsHandler = (props) => {
        if (props.rotation){
            rotation = props.rotation * Math.PI / 180
        }
    }

    //毎フレームごとの描画内容
    p.draw = () => {
        p.background(100)
        p.normalMaterial()
        p.noStroke()
        p.push()
        p.rotateY(rotation)
        p.box(100)
        p.pop()
    }
}

export default testSketch
```

上記では,WebGLモードでcanvas要素を生成し,その中に立体の箱を生成します.

そしてコマンドラインにて以下のコマンドを実行してローカルサーバを立ち上げ,結果を確認してみます.

```terminal.
yarn run start
```

ブラウザで確認して,以下のように表示されれば成功です！！

<img width="1280" alt="スクリーンショット 2019-08-07 0.21.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386550/d2c4bd09-ec55-9365-fe63-2beda3c750e9.png">

通常,processingやp5.jsは`setup, draw`などと書くのですが,`react-p5-wrapper`では`p.setup, p.draw`のように記述します.

これはp5.jsに存在する関数や定数を一切合切全てpという名前のインスタンスとして渡しているからです.
ちょっとめんどくさいですが, p5.js由来の関数・メソッド・定数には全て`p.`とつけてください.

では次にP5Wrapperコンポーネントにプロパティを渡してみます.
以下のように,`rotation={45}`という記述を追加します.

```src/App.js
...

const App = () => (
+   <P5Wrapper sketch={testSketch} rotation={45} />
)

...
```

そして結果を確認すると,以下のように45°回転していることが確認できると思います.
ちゃんと立体ですね.

<img width="1280" alt="スクリーンショット 2019-08-07 0.45.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386550/1811e796-bd3f-12e3-baea-43de0f58cf83.png">

それでは,さらにReactっぽい書き方をしながらこれを改造していきましょう.

今回は,バーによって回転具合を調節できるようにしてみます.
なお,これはreact-p5-wrapperのsampleを簡略化して実装したものです.

[https://github.com/and-who/react-p5-wrapper](https://github.com/and-who/react-p5-wrapper)

では早速やっていきましょう.
まずAppコンポーネントをクラスとして書き直しましょう.

```src/App.js
import React, { Component } from 'react'
import P5Wrapper from 'react-p5-wrapper'
import testSketch from './testSketch'
import './App.css'

class App extends Component{

  //初期値を45°に設定
  constructor(props) {
    super(props)
    this.state = {
      rotation: 45,
    }
  }

  //バーの値が変化するごとに回転角を変更
  rotationChange(e){
    this.setState({rotation:e.target.value});
  }

  //コンポーネントの描画
  //生成されるcanvasの下にバーを置く
  render () {
    return (
        <div>
          <P5Wrapper sketch={testSketch} rotation={this.state.rotation} />
          <input type="range" value={this.state.rotation}  min="0"  max="360" step="1" onInput={this.rotationChange.bind(this)}/>
		</div>
    )
  }
}

export default App
```

sketchの方を変更する必要はありません.

コマンドラインにて`yarn run start`を実行すると,以下のように動作させることができると思います.


![名称未設定.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386550/c1ee5c50-c250-dc07-5373-a05ccf0e1bde.gif)
(アス比違くないですか())

上記コードでは,バーの値が変化すると,そのイベントを受け取って新しい回転角をstateに設定します.

描画される箱の回転角は,P5Wrapperに渡されているrotationの値によって決まるので,上記のような表現が可能です.

また,sketchにて`p.rotateY(rotation)`としていますが,`p.rotateX(rotation)`や`p.rotateZ(rotation)`に変更したり,追記することで異なった挙動を実現することもできます.

今回は以上で終わりです！最後にgithub pagesにデプロイしておきましょう.

```terminal.
yarn run deploy
```

お疲れ様でした！

# まとめ

次回はp5.jsを生かした作品を作り,Webサイトとして公開するところまでやっていきます.

いい感じにかっこよくなるといいですね(したい).