環境
- react: 18.0.0
- react-dom: 18.0.0
- three: 0.139.2
- next: 12.1.0
- react-three/drei: 9.2.0
- react-three/fiber: 8.0.10
- typescript: 4.6.2
1. 導入
そもそも、この構成でやっている記事が少なく、動くようになるまで少し手間取ったため記事を書くことにしました。
もっと良い方法があったら教えて頂けると助かります。
2. 手順
①プロジェクトを作成
yarn create next-app
②各種 yarn add
③ディレクトリ構成
components/
┣ Model.tsx
┣ DrawCanvas.tsx
pages/
┣ _app.tsx
┣ index.tsx
public
┣ モデルファイル
④モデル用コンポーネント定義
Model.tsx
import { useGLTF } from "@react-three/drei"
const Model = () => {
const gltf = useGLTF('/house.glb')
return (
<primitive object={gltf.scene} />
)
}
export default Model
⑤キャンバス用コンポーネント定義
DrawCanvas.tsx
import { Suspense } from 'react'
import { OrbitControls, Stage } from '@react-three/drei'
import { Canvas } from '@react-three/fiber'
import dynamic from 'next/dynamic'
const Model = dynamic(() => import('../components/Model'))
const DrawCanvas = () => (
<Suspense fallback={<span>loading</span>}>
<Canvas>
<OrbitControls />
<Stage>
<Model />
</Stage>
</Canvas>
</Suspense>
)
export default DrawCanvas
⑥pageに配置
index.tsx
import type { NextPage } from 'next'
import DrawCanvas from '../components/DrawCanvas'
const Home: NextPage = () => (
<>
<DrawCanvas />
</>
)
export default Home
3. 注意点
- useGLTFなどのモデル読み込みを、キャンバスを定義するコンポーネント(DrawCanvas.tsx)のスコープの中で行うとうまく行かなかった
- モデル用のコンポーネントを別に定義する必要がある
- 別ファイルに定義したモデル用コンポーネントは dynamic import する必要がある
- Suspenseを使う場合、Suspenseの中にCanvasを配置する必要がある
- 表示されたキャンバスはデフォルトでは大きさや比率がおかしいので、cssなどでスタイリングする必要がある