SplineのデータをReact Three Fiberで扱う

## この記事の概要

[Spline](https://spline.design/)という3Dデザインツールがあります。
エクスポート機能でコード化でき、vanillaのJavaScript、Three.js、React、React Three Fiberに対応しています。

この中で[React Three Fiber版](https://github.com/splinetool/r3f-spline)は若干ドキュメントが不足している感があったので、使い方を記事にしました。

## Spline上での説明

画面上部、ヘッダーの`Export`を押すと小さなウインドウが開きます。
その中の`Code (Experimental) > react-three-fiber`を選ぶと、`Overview`タブの`Code`エリアに、React Three Fiberに準拠したコードが生成されます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/d4f1d8dc-de44-539f-2a4b-6047338db05e.jpeg)

生成されるコードは次のような感じです。
ジオメトリやマテリアルはSplineのデータ（scene.splinecode）から取得していますが、カメラやライトの設定はコード上で微調整もしやすいので便利そうですね。

```javascript
/*
  Auto-generated by Spline
*/

import useSpline from '@splinetool/r3f-spline'
import { PerspectiveCamera } from '@react-three/drei'

export default function Scene({ ...props }) {
  const { nodes, materials } = useSpline('https://prod.spline.design/FILE_ID/scene.splinecode')
  return (
    <>
      <color attach="background" args={['#5e6063']} />
      <group {...props} dispose={null}>
        <PerspectiveCamera
          name="Camera"
          makeDefault={true}
          far={10000}
          near={5}
          fov={45}
          position={[600, 600, 900]}
          rotation={[-Math.PI / 6, Math.PI / 6, 0.26]}
        />
        <directionalLight
          name="Directional Light"
          castShadow
          intensity={0.7}
          shadow-mapSize-width={1024}
          shadow-mapSize-height={1024}
          shadow-camera-near={-10000}
          shadow-camera-far={100000}
          shadow-camera-left={-500}
          shadow-camera-right={500}
          shadow-camera-top={500}
          shadow-camera-bottom={-500}
          position={[200, 300, 300]}
        />
        <mesh
          name="Rectangle"
          geometry={nodes.Rectangle.geometry}
          material={materials['Rectangle Material']}
          castShadow
          receiveShadow
        />
        <hemisphereLight name="Default Ambient Light" intensity={0.75} color="#eaeaea" />
      </group>
    </>
  )
}
```

## 足りない依存関係

コードは出力されますが、このままでは動きません。
エラーやpackage.jsonを見ながら足りない依存関係を調べていましたが、普通に面倒くさかったので一覧にします。
特に`@react-three/drei`はサンプルコードに存在しているものの、ドキュメントには記載がありません。

- @react-three/drei
- @react-three/fiber
- @splinetool/loader
- @splinetool/r3f-spline
- three

コピペできるようにコマンド化しても記載しておきます。

```shell
npm i @react-three/drei @react-three/fiber @splinetool/loader @splinetool/r3f-spline three
# OR
yarn add @react-three/drei @react-three/fiber @splinetool/loader @splinetool/r3f-spline three
```

## ざっくりしたコードの構成

コードを書くときの例も記載します。
例なので1つのファイルとしてまとめてしまっていますが、実際は適宜分割してください。

```javascript:App.js
import { OrbitControls, PerspectiveCamera } from '@react-three/drei'
import { Canvas } from '@react-three/fiber'
import useSpline from '@splinetool/r3f-spline'

const Scene = ({ ...props }) => {
  const { nodes, materials } = useSpline('https://prod.spline.design/FILE_ID/scene.splinecode')
  return (
    // シーンの内容色々
  )
}

export default function App() {
  return (
    <Canvas>
      <Scene />
      <OrbitControls />
    </Canvas>
  )
}
```

## 最後に

「React Three Fiber用」と謳っている中で`@react-three/drei`が普通に出てきて「気持ちは分かるけど……笑」となりました。
エラーを読めば単なる依存関係の不足だと分かりますが、ドキュメントに書いてあるまま動かしているのに動かないと、少し驚いてしまいます。
似たような内容で困った人がいたら、その人の助けになれれば幸いです。

---

最後まで読んでくださってありがとうございます！
Twitterでも情報を発信しているので、良かったらフォローお願いします！

https://twitter.com/xrxoxcxox

Devトークでのお話してくださる方も募集中です！

https://jobs.qiita.com/employers/qiita-inc/dev_talks/489