前端技术, 开发

React Three 学习笔记

基本概念

React Three Fiber

React Three Fiber 基于 Three.js,是 Three.js 的 React 绑定,为 React 开发者提供了一种简单、直观的方式来创建和管理 3D 场景。

React Three Fiber 官方文档

安装

首先 安装 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样式来定义父容器尺寸。

官方文档:Canvas

常用属性

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>

    PUJI Design 朴及设计 (c) 2024. 沪ICP备17052229号