💡

@react-three/dreiって、TypeScriptじゃ動かんくね?00x(Stats, OrbitControls)

2023/12/23に公開

Abstract

@react-three/dreiのサンプルコード、JavaScriptだと結構あるけど、TypeScriptだと全然ない。JavaScriptから興すとビルドエラーやし。
どげんか動かしたる。
今回はこれ

結論

今回の成果物はココ↓
https://github.com/aaaa1597/react-drei-react-typescript

前提

前準備

1.プロジェクト生成 -> VSCodeで開く

めんどいから、これ→React-Ts-Templateを雛形にする。
で、下記コマンドでフォルダ名とか整備する。

フォルダリネームとか
$ BaseProject=React-Ts-Template
$ NewProject=react-drei-react-typescript
$ cd ~
$ git clone https://github.com/aaaa1597/${BaseProject}.git
$ rm -rf ${BaseProject}/.git
$ rm -rf ${react}
$ mv ${BaseProject} ${react}

2.生成したプロジェクトの場所でthree.jsとかR3Fとかインストール

$ cd ~
$ cd react-drei-react-typescript
$ npm install
$ npm install --save three
$ npm install --save @types/three
$ npm install --save @react-three/fiber
$ npm install --save @react-three/drei

App.tsxを作っていく

App.tsxの全体

App.tsx
-import React from 'react';
+import React, { Suspense, useRef } from 'react';
+import { Canvas, ThreeElements, useFrame } from "@react-three/fiber";
+import { Stats, OrbitControls } from "@react-three/drei";
+import * as THREE from "three";
import './App.css';

+const Cube = () => {
+  const cube = useRef<THREE.Mesh>(null!)
+
+  useFrame(() => {
+    cube.current!.rotation.x += 0.01;
+    cube.current!.rotation.y += 0.01;
+  });
+
+  return (
+    <mesh ref={cube}>
+      <boxGeometry args={[3, 3, 3]} />
+      <meshBasicMaterial color="#0391BA" />
+    </mesh>
+  );
+};

+const Scene = () => {
+  return (
+    <>
+      <gridHelper />
+      <axesHelper />
+      <pointLight intensity={1.0} position={[5, 3, 5]} />
+      <Cube />
+    </>
+  );
+};

-function App() {
+const App = () => {
  return (
-    <div className="App">
-      hello world!!
+    <div style={{ height: "75vh", width: "75vw"}}>
+      <Canvas camera={{ near: 0.1, far: 1000, zoom: 1 }} onCreated={({ gl }) => {gl.setClearColor("#227700") }}>
+      <Stats />
+      <OrbitControls />
+      <Suspense fallback={null}>
+      <Scene />
+      </Suspense>
+      </Canvas>
    </div>
  );
}

export default App;


出来た!!

ポイント

1.<Stats/>

統計情報(fpsとか)を表示してくれるやつ。
dreiをインストールとimportしとく必要がある。
↓これ

2.dreiをimportする発生するエラー。

↓こいつに苦しんだ。

App.tsx
-  const cube = useRef<THREE.Mesh>()
+  const cube = useRef<THREE.Mesh>(null!)

引数に"null!"を追加すれば直ったけど、エラーが全然分かんない。
こんなエラー出ても分かんねーよ。初心者に優しくない。

エラーの内容
ERROR in src/App.tsx:16:11
TS2322: Type 'MutableRefObject<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | undefined>' is not assignable to type 'Ref<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap>> | undefined'.
  Type 'MutableRefObject<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | undefined>' is not assignable to type 'RefObject<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap>>'.
    Types of property 'current' are incompatible.
      Type 'Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | undefined' is not assignable to type 'Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | null'.
        Type 'undefined' is not assignable to type 'Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | null'.
    14 |
    15 |   return (
  > 16 |     <mesh ref={cube}>
       |           ^^^
    17 |       <boxGeometry args={[3, 3, 3]} />
    18 |       <meshBasicMaterial color="#0391BA" />
    19 |     </mesh>

3.<OrbitControls />

マウスの動きに合わせて、視点をグリグリ変えてくれるやつ。
詳細はこっち

4.<Suspense/>

ロード中の待ち画面を表示してくやつ。詳細はこっち

App.tsx
   <Suspense fallback={<div>ロード中はこれが表示される</div>}>
     <MyComponent />
   </Suspense>

5.<gridHelper />

格子状の板を表示してくれるやつ。オブジェクトの位置を確認しやすくなる。

6.<axesHelper />

3軸の線を表示してくれるやつ。回転状況が分かりやすくなる。

以上。

Discussion