@react-three/dreiって、TypeScriptじゃ動かんくね?気合で動かしてみた001(PerspectiveCamera)

2024/01/03に公開

Abstract

@react-three/dreiが便利!!って見るけど、全然親切じゃない。一番最初のPerspectiveCameraから分からんかったし。
なので、サンプルコードと解説を日本語で残します。
あっ、ちなみに、react-three/dreiって、React Three Fiber(R3F)のサポートライブラリね。

結論

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

前提

準備

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

めんどいから、このスケルトンコードから始める。react-r3f-base-onebox
で、下記コマンドでフォルダ名とか整備する。

フォルダリネームとか
$ D:
$ cd .\Products\React.js\            # ご自身の適当なフォルダで。
$ rd /q /s react-r3f-base-onebox
$ git clone https://github.com/aaaa1597/react-r3f-base-onebox.git
$ rd /q /s react-r3f-base-onebox/.git
$ ren react-r3f-base-onebox react-drei-1camera-perspective
$ cd react-drei-1camera-perspective

2.必要ライブラリのインストール

$ 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
import React, {useRef} from 'react';
import './App.css';
import { Canvas, useFrame, MeshProps, useThree } from '@react-three/fiber'
import * as THREE from 'three'
-import { OrbitControls, Environment } from '@react-three/drei'
+import { OrbitControls, Environment, PerspectiveCamera } from '@react-three/drei'

const Box = (props: MeshProps) => {
  const ref = useRef<THREE.Mesh>(null!)

  useFrame((_, delta) => {
    if( !ref.current) return
    ref.current.rotation.x += 1 * delta
    ref.current.rotation.y += 0.5 * delta
  })

  return (
    <mesh {...props} ref={ref}>
      <boxGeometry />
      <meshNormalMaterial />
    </mesh>
  )
}

+const Rig = () => {
+  const {camera} = useThree()
+  return useFrame(() => {
+    camera.position.lerp(new THREE.Vector3(0, 3, 10), 0.05)
+    camera.lookAt(0, 0, 0)
+  })
+}
+
const App = () => {
  return (
    <div style={{ width: "100vw", height: "75vh" }}>
      <Canvas camera={{ position: [0, 3, 5] }}>
+       <PerspectiveCamera makeDefault position={[0, -100, 10]}/>
        <Box position={[1, 1, 1]} name="A" />
        <Environment preset="forest" background />
        <OrbitControls />
        <axesHelper args={[5]} />
        <gridHelper />
+       <Rig />
      </Canvas>
    </div>
  );
}

export default App;

で、実行。


出来た!!
起動直後に舞台が上から下に降りてくる感じが描画できてる。

ポイント

独自関数コンポーネントの<Rig />について

動作検証用に、Rig関数を作っている。
PerspectiveCameraって、positionにちょっと違う値を入力すると、一体どこに行ったんだ?みたいになってちゃんと動いてるのか全然分からんかったけん。
この関数が動くことで、{x:0, y:3, z:10}の位置に戻るようにした。

App.tsx
  camera.position.lerp(new THREE.Vector3(0, 3, 10), 0.05)
  camera.lookAt(0, 0, 0)

PerspectiveCameraについて

ここからが、本題。DreiのPerspectiveCameraの値を変更して変化を見ると良くわかる。
今回は[0, -100, 10]を設定したので、視点(カメラ)が下から上に移動したので、舞台が下りてくるような動きが表現できた。

カメラ位置の初期値について

今回Canvasにもカメラ(視点)位置を設定してて、PerspectiveCameraにも位置を指定しているが、その場合どうもPerspectiveCameraが有効になってそう。たぶんPerspectiveCameraの方が後に動くからじゃないだろうか。
で、Canvasも、PerspectiveCameraにも設定しなかった場合は、[0,0,5]が設定されてそう。

すこし、Camera(視点)の扱いが分かってきた気がする。

Discussion