基本概念
React Three Fiber
React Three Fiber 基于 Three.js,是 Three.js 的 React 绑定,为 React 开发者提供了一种简单、直观的方式来创建和管理 3D 场景。
安装
首先 安装 React 脚手架。
然后安装 React Three Fiber
npm install three @types/three @react-three/fiber
基本使用
import ReactDOM from 'react-dom/client';
import { Canvas } from '@react-three/fiber';
const root = ReactDOM.createRoot( document.querySelector( '#root' ) );
root.render(
<Canvas>
<mesh position-x={ -2 } rotation-y={ Math.PI * 0.5 } >
<torusKnotGeometry />
<meshNormalMaterial />
</mesh>
<mesh position={ [ 2, 0, 0 ] } scale={ 1.5 } >
<torusKnotGeometry />
<meshNormalMaterial />
</mesh>
</Canvas>
);
// 创建场景
const scene = new THREE.Scene()
// 添加物体
const geometry = new THREE.BoxGeometry( 1, 1, 1 )
const material = new THREE.MeshBasicMaterial({ color: "purple" })
const mesh = new THREE.Mesh( geometry, material )
scene.add( mesh )
// 添加摄像机
const aspect = {
width: window.innerWidth,
height: window.innerHeight
}
const camera = new THREE.PerspectiveCamera( 75, aspect.width/aspect.height, 1, 2000 )
camera.position.x = 1
camera.position.y = 1
camera.position.z = 3
scene.add( camera )
// 渲染场景
const canvas = document.querySelector( "canvas" )
const renderer = new THREE.WebGLRenderer({ canvas: canvas })
renderer.setSize( aspect.width, aspect.height )
renderer.render( scene, camera )
组件
Canvas
使用 Canvas 组件将自动创建场景、camera、raycaster、canvas 元素以及 WebGL 渲染器。
Canvas 渲染的尺寸由该元素的父容器尺寸决定,因此可以修改css样式来定义父容器尺寸。
常用属性
camera 摄像机
camera={{
fov: 45,
near: 0.1,
far: 100,
zoom: 10,
postion: [ 10, 10, 0 ]
}}
gl
gl={
antialias: true, // 抗锯齿
alpha: true, // 背景为透明
}
onCreated
onCreated={ () => {}}
Hooks
useFrame
useFrame( () => {
...
} )
import { useRef } from 'react'
import * as THREE from 'three'
import { useFrame } from '@react-three/fiber'
export const Scene = () => {
const cubeRef = useRef()
const planeRef = useRef()
useFrame( ( state, delta ) => {
cubeRef.current.rotation.y += delta
planeRef.current.rotation.y += delta
} )
return (
<>
<mesh ref={ planeRef } position-x={ -2 } >
<planeGeometry args={ [ 2, 2 ] } />
<meshBasicMaterial color="orange" side={ THREE.DoubleSide } />
</mesh>
<mesh ref={ planeRef } position-x={ -2 } >
<boxGeometry />
<meshBasicMaterial color="#7a00ca" />
</mesh>
</>
)
}
useThree
useLoader
import * as THREE from 'three'
import { useLoader } from '@react-three/fiber'
const texture = useLoader( THREE.TextureLoader, '.image.png' )
粒子
<points>
<spherGeometry />
<pointsMaterial size={ 0.02 }
</points>
加载模型
import { useGLTF } from '@react-three/drei'
const model = useGLTF( './model.glb' )
<primitive object={ model.scene } />
Suspense
实现资源加载完成后再显示里面的组件,fallback 属性可以在组件未加载完成前显示替代内容
import { Suspense } from 'react'
<Suspense fallback={ <mesh>...</mesh> } >
<Model />
</Suspense>
将模型转换为 jsx 文件
npx gltfjsx model.gltf
鼠标事件
- onClick
- onContextMenu
- onDoubleClick
- onWheel
- onPointerUp
- onPointerDown
- onPointerOver
- onPointerOut
- onPointerEnter
- onPointerLeave
- onPointerMove
- onPointerMissed
- onUpdate // 属性值更新
辅助功能
<axesHelper />
<gridHelper />
调试工具
npm install leva
import { useControls } from 'leva'
const { position, color, wireframe, scale } = useControls( 'cube', {
position: {
value: {
x: 0,
y: 0,
z: 0,
},
min: -10,
max: 10,
step: 0.01,
}
color: '#ffffff',
wireframe: false,
click:button(() => {})
scale: { options: [ 1, 2, 3 ]}
})
<mesh postion={ [ position.x, position.y, position.z ]} scale={ scale }>
<boxGeometry />
<meshStandardMaterial color={ color } wireframe={ wireframe } />
</mesh>