从零开始探索 @react-three/fiber 与 @react-three/drei:构建3D Web应用的现代方式

19 阅读5分钟

在Web开发中,随着用户对交互体验和视觉效果要求的提升,3D图形的应用变得越来越普遍。而React作为前端开发的主流框架之一,与Three.js(一个强大的JavaScript 3D库)结合后,开发者可以用更现代化的方式构建高性能的3D场景。@react-three/fiber@react-three/drei 是这一生态中的两个关键库,它们极大地简化了React中使用Three.js的过程。

本文将由浅入深地介绍这两个库,并通过知识扩展帮助你理解其背后的原理和应用场景。


一、什么是 @react-three/fiber?

简介

@react-three/fiber 是一个基于 ReactReconciler(协调器),它允许你在React组件中直接使用Three.js对象(如相机、灯光、几何体等),并自动管理渲染循环、性能优化、状态同步等底层逻辑。

简单来说,它让Three.js的使用方式更加“React化”——你可以像写普通React组件一样来编写3D内容。

安装

npm install @react-three/fiber three

基本用法

以下是一个简单的示例,展示如何在React中创建一个旋转的立方体:

import React from 'react'
import { Canvas } from '@react-three/fiber'
import { MeshStandardMaterial, BoxGeometry } from 'three'

function Box() {
  return (
    <mesh>
      <boxGeometry />
      <meshStandardMaterial />
    </mesh>
  )
}

export default function App() {
  return (
    <Canvas>
      <ambientLight />
      <pointLight position={[10, 10, 10]} />
      <Box />
    </Canvas>
  )
}

在这个例子中:

  • <Canvas> 是一个包裹Three.js渲染器的容器。
  • <mesh> 表示一个3D网格对象。
  • <boxGeometry /> 是一个立方体几何体。
  • <meshStandardMaterial /> 是一种带有光照响应的材质。

特性亮点

  • 声明式编程:像写HTML一样写3D对象。
  • 自动更新机制:React状态变化时自动触发渲染更新。
  • 性能优化:支持暂停、懒加载、并发模式等高级特性。
  • TypeScript支持:开箱即用的类型定义。

二、什么是 @react-three/drei?

简介

@react-three/drei 是一个工具包(Utility Library),为 @react-three/fiber 提供了一系列高阶组件和实用函数,用于简化常见的3D开发任务,比如加载模型、添加环境光、设置相机控制等。

它的名字来源于德语单词“Drei”,意思是“三”,寓意它是Three.js的辅助工具。

安装

npm install @react-three/drei

常见功能举例

1. 相机控制器(OrbitControls)

import { OrbitControls } from '@react-three/drei'

<Canvas>
  {/* ...其他内容 */}
  <OrbitControls />
</Canvas>

这个组件让你可以通过鼠标拖动来旋转、缩放视角。

2. 加载GLTF模型(例如使用Loaders)

import { useGLTF } from '@react-three/drei'

function Model({ url }) {
  const { scene } = useGLTF(url)
  return <primitive object={scene} />
}

这段代码可以轻松加载 .gltf.glb 格式的3D模型文件。

3. 添加环境光和背景(Environment)

import { Environment } from '@react-three/drei'

<Canvas>
  <Environment preset="city" />
  {/* 其他模型 */}
</Canvas>

Environment 组件可以快速为场景添加HDRI环境贴图,增强真实感。

4. 动态阴影(Shadows)

<Canvas shadows>
  <directionalLight castShadow position={[5, 10, 7]} />
  <mesh receiveShadow castShadow>
    <boxGeometry />
    <meshStandardMaterial />
  </mesh>
</Canvas>

只需开启 shadows 属性,并设置 castShadowreceiveShadow 即可启用阴影效果。


三、两者的关系与协作

角色功能
@react-three/fiber基础引擎将Three.js对象映射为React组件,提供渲染上下文
@react-three/drei工具库提供封装好的常用功能,简化开发流程

它们之间的关系类似于:

  • fiber 是“发动机”;
  • drei 是“方向盘 + 雨刷 + 空调”等辅助驾驶系统。

二者结合,才能发挥出最大的生产力。


四、进阶实践:构建一个带交互的3D画廊

我们可以尝试构建一个简单的3D画廊页面,展示多个模型,并支持点击查看详细信息。

技术栈

  • React
  • @react-three/fiber
  • @react-three/drei
  • GLB/GLTF模型资源

实现思路

  1. 使用 <Canvas> 创建3D空间;
  2. 使用 <ScrollControls><Scroll> 控制滚动加载;
  3. 使用 <Center><Text> 显示文字说明;
  4. 使用 useGLTF 加载模型;
  5. 添加交互事件(如点击跳转或弹窗)。

示例代码片段

import { Canvas, useFrame } from '@react-three/fiber'
import { ScrollControls, Scroll, Text, Center, Image } from '@react-three/drei'

function Artwork({ modelUrl, title }) {
  const { scene } = useGLTF(modelUrl)
  return (
    <group>
      <primitive object={scene} scale={2} />
      <Text fontSize={0.5} color="white">
        {title}
      </Text>
    </group>
  )
}

export default function Gallery() {
  return (
    <Canvas camera={{ position: [0, 0, 5] }}>
      <ScrollControls>
        <Scroll>
          <Center>
            <Artwork modelUrl="/models/art1.glb" title="艺术作品 A" />
          </Center>
          <Center>
            <Artwork modelUrl="/models/art2.glb" title="艺术作品 B" />
          </Center>
        </Scroll>
      </ScrollControls>
    </Canvas>
  )
}

五、知识扩展:Three.js 与 React 生态的融合趋势

1. 性能优化与WebGPU

目前 @react-three/fiber 主要基于 WebGL 渲染,但随着 WebGPU 的普及,未来可能会有基于 WebGPU 的版本出现,带来更高的性能和跨平台能力。

2. 与 Zustand / Redux 状态管理结合

在复杂项目中,可以使用 Zustand 或 Redux 来管理3D场景的状态(如相机位置、模型数据、动画状态等),从而实现更好的状态共享与调试。

3. 与 Next.js / Gatsby 集成

越来越多的React静态站点生成器(SSG)支持服务端渲染(SSR),但Three.js本身不支持SSR。@react-three/fiber 提供了解决方案,比如动态导入组件,避免SSR报错。

const DynamicComponentWithNoSSR = dynamic(() => import('../components/My3DScene'), {
  ssr: false,
})

六、总结

模块内容
@react-three/fiber将Three.js组件化,让3D开发更符合React范式
@react-three/drei提供丰富的辅助组件和工具,提高开发效率
开发优势声明式语法、状态同步、良好的TypeScript支持
扩展方向与WebGPU、Zustand、Next.js等技术结合

如果你是前端开发者,想要进入3D领域,那么 @react-three/fiber@react-three/drei 是不可错过的选择。它们不仅降低了Three.js的学习门槛,也提供了强大的扩展能力和社区支持。


参考资料


如果你喜欢这篇文章,欢迎点赞、分享,或者订阅我的博客获取更多关于React与3D开发的内容!