React Three Fiber(R3F)勉強1: プロジェクトを作りたい

# はじめに
以前、[Reactのチュートリアルをまとめた記事](https://qiita.com/skm_bnn/items/64fa6ccb58101eadbb63) を投稿しました。今回は、 React Three Fiber(R3F)を勉強して、Reactアプリケーション上で3Dグラフィックスを動かせるようにしていきます。~~筆者はThree.jsすら触ったことがない全くのド素人ですが、公式リファレンスを頼りにR3Fの基礎を固めていきたいと思います。~~ あまりにも、R3Fを理解できなかったため、Three.jsを勉強中です。そのため、本記事の更新はかなり遅くなります。

# R3Fとは？
R3Fは、ReactのコンポーネントベースのアーキテクチャとThree.jsの3Dグラフィックス機能を組み合わせたものです。これにより、直感的に3Dアプリケーションの開発ができるとのことなので勉強をしていきたいと思います。

# プロジェクトのセットアップ
R3Fのプロジェクトをローカル環境で作成していきます。プロジェクトファイル名は```sample0```とします。

## Reactプロジェクトの作成
手動でプロジェクトの作成をしていきます。[この記事](https://qiita.com/skm_bnn/items/30f5d9d2c5eea00ac11c#%E6%96%B9%E6%B3%95a)と類似した内容であるため、既知である方は[R3Fの導入](#R3Fの導入)までとばしてください。

### package.jsonの作成
次のコマンドでpackage.jsonを作成します。

```
# package.jsonの作成
npm init -y
```

### Reactに関するパッケージの導入
次のコマンドで3つのReactに関するパッケージをプロジェクトディレクトリにインストールしていきます。
```
npm install react react-dom react-scripts
```

ここで、package.jsonの内容は次のように変更されています。
``` json:package.json
{
  "name": "sample0",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "^5.0.1"
  }
}
```

### package.jsonの編集
package.jsonの内容を次のように編集します。```scripts```フィールドの内容が変更されており，```browserslist```と```development```フィールドが追加されていることを確認してください。
```json: package.json
{
  "name": "sample0",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
    },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "^5.0.1"
  }
}
```

### ファイルの作成
複数のファイルを作成していきます。次のディレクトリ構成を作成して、各ファイルの内容をコピペで変更してください。

```
sample0
- package.json
- node_modules
- public
  - index.html
- src
  - index.js
  - App.js
```

#### public フォルダ
##### index.html ファイル
```html:index.html
<!DOCTYPE html>
<html lang="ja">

  <head>
    <!-- 文書の文字エンコーディングをUTF-8に指定 -->
    <meta charset="UTF-8">
    <!-- ページのタイトルを指定 -->
    <title>R3F練習</title>
  </head>

  <body>
    <!-- Reactアプリケーションが描画されるルート要素の定義 -->
    <div id="root"></div>
  </body>

</html>
```

#### src フォルダ
##### index.js ファイル
```jsx: index.js
// ReactおよびReactDOMをインポート
import React from 'react';
import ReactDOM from 'react-dom/client';

// Appコンポーネントを'./App'からインポート
import App from './App';

// ルート要素を特定のDOM要素に関連付ける
const root = ReactDOM.createRoot(document.getElementById('root'));

// ルート要素にReactコンポーネントを描画する
root.render(
  // React.StrictModeコンポーネントでアプリケーションをラップする
  <React.StrictMode>
    {/* Appコンポーネントを描画 */}
    <App />
  </React.StrictMode>
);
```

##### App.js ファイル
このファイルは後の3Dシーンを描画する際に再び内容を変更します。
```jsx:App.js
// Appコンポーネントの定義
function App() {
  return (
    <div className="App">
      <h1>Hello, R3F!</h1>
    </div>
  );
}

// Appコンポーネントを他のファイルで利用できるようにエクスポート
export default App;
```

### 動作確認
次のコマンドを実行します。
```
npm start
```

「Hello, R3F!」と記載されたページが表示されると成功です。

![動作結果1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/31f65b13-d0c1-d4b4-7f81-341c7421a192.jpeg)


## R3Fの導入
R3Fを扱うために必要なパッケージのインストールと簡単な3Dシーンを作成していきます。

### R3Fパッケージのインストール
次のコマンドでR3Fに関するパッケージをインストールします。
```
npm install three @react-three/fiber

```

### 3Dシーンの作成
App.jsファイルの内容を次のように変更します。今回の記事では、プログラムの内容を理解するのではなく、R3Fの動作を確認できることに重きを置かせていただきます。

```jsx: App.js
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'

// ボックス(立方体)のコンポーネントを定義
function Box(props) {
  // メッシュへアクセスする
  const meshRef = useRef()

  // 状態の設定
  const [hovered, setHover] = useState(false) // マウスが被っているか否か
  const [active, setActive] = useState(false) // マウスクリックで変化

  // メッシュをフレームごとに回転させます
  useFrame((state, delta) => (meshRef.current.rotation.x += delta))

  // コンポーネントを描画する
  return (
    <mesh
      {...props}
      ref={meshRef}
      scale={active ? 1.5 : 1}
      onClick={(event) => setActive(!active)}
      onPointerOver={(event) => setHover(true)}
      onPointerOut={(event) => setHover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

// アプリケーションのエントリーポイントとなるコンポーネントを定義
function App() {
  return (
    <div className="App">
      <Canvas>
        <ambientLight />
        <pointLight position={[10, 10, 10]} />
        {/* Boxコンポーネントを配置 */}
        <Box position={[-1.2, 0, 0]} />
        <Box position={[1.2, 0, 0]} />
      </Canvas>
    </div>
  );
}

// Appコンポーネントを他のファイルで利用できるようにエクスポート
export default App;
```

このプログラムはR3Fの公式ドキュメントに従ったものです。

https://docs.pmnd.rs/react-three-fiber/getting-started/introduction

# 動作確認
実行に成功すると2つの立方体が描画されます。各立方体は回転しています。立方体に対して、マウスホバーすると色，マウスクリックすると大きさが変化します。

![動作結果2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/ddb832a7-cadb-a462-5d03-a5e4c3c9d65b.gif)

# おわりに
この記事ではR3Fが動作できるようにプロジェクトディレクトリを作成しました。これからは、R3Fの構文の基礎にしっかりと触れることで、勉強していきたいと思います。


# 参考文献
- React Three Fiber

https://docs.pmnd.rs/react-three-fiber/getting-started/introduction