news 2026/9/11 7:27:33

react-three-fiber 完全指南:用 React 声明式渲染 Three.js 3D 场景

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
react-three-fiber 完全指南:用 React 声明式渲染 Three.js 3D 场景

react-three-fiber 完全指南:用 React 声明式渲染 Three.js 3D 场景

【免费下载链接】react-three-fiber🇨🇭 A React renderer for Three.js项目地址: https://gitcode.com/GitHub_Trending/re/react-three-fiber

react-three-fiber(简称 R3F)是一个面向 Three.js 的 React renderer(渲染器),它让你可以用声明式的 JSX 组件构建 3D 场景,组件可复用、自带状态、可交互,并且能无缝融入 React 的整个生态系统。本文将基于本仓库(@react-three/fiberv9)的官方 README 与核心源码,系统讲解它的安装配置、核心概念、JSX/TypeScript/React Native 三端实战示例,并深入其 Canvas、Hooks、Store 等底层实现原理,读完即可上手写出自己的第一个可交互 3D 应用。

什么是 react-three-fiber

一句话概括:react-three-fiber 是一个把 Three.js 变成 React 组件的渲染器。它的核心理念是——用声明式、可复用、自带状态的组件来构建场景,这些组件能够响应状态变化、天然可交互,并参与 React 生态:

  • 复用 React 的组件化思想组织 3D 对象树;
  • 组件内部的useStateuseRefuseFrame等让场景拥有自己的行为逻辑;
  • 与 React 的 Suspense、事件系统、状态管理库无缝配合。

Three.js 中的所有导出类型对 three-fiber 而言都是"原生"的:<mesh />会动态地变成new THREE.Mesh()<ambientLight />变成new THREE.AmbientLight(),无需任何手动注册。

安装与版本配对

安装只需一条命令:

npm install three @types/three @react-three/fiber

这里安装了三个包:Three.js 本体、它的 TypeScript 类型定义,以及 react-three-fiber 渲染器。

警告:版本配对是硬性要求Three-fiber 是一个 React 渲染器,它必须与某个 React 大版本配对使用,就像 react-dom、react-native 一样。例如:@react-three/fiber@8配对react@18@react-three/fiber@9配对react@19

本仓库中的 packages/fiber/package.json 给出了当前版本(9.6.1)的精确配对关系,可作为对照:

{ "peerDependencies": { "react": ">=19 <19.3", "react-dom": ">=19 <19.3", "react-native": ">=0.78", "three": ">=0.156" } }

可以看到,v9 要求 React 19(>=19 <19.3)、Three.js>=0.156react-domreact-native均为可选 peer 依赖,这正是同一份代码可以同时跑在 Web 与 React Native 上的原因。安装前请务必检查你的 React 主版本,避免渲染器与运行时版本错配导致的异常。

常见疑问解答(FAQ)

README 用三个问答快速回应了开发者最常见的顾虑:

Q:它有局限吗?

没有。凡是在 Three.js 中能工作的东西,在这里都能工作,无一例外。

Q:它比纯 Three.js 慢吗?

不慢。没有额外开销,组件在 React 之外渲染。得益于 React 的调度能力,它在规模上反而优于 Three.js。

Q:它能跟上 Three.js 频繁的版本更新吗?

能。它只是把 Three.js 表达为 JSX,<mesh />动态地变成new THREE.Mesh()。如果 Three.js 新版本新增、移除或修改了某个特性,它会立刻可用,无需等待本库发版

第三条从源码上可以得到印证:在 packages/fiber/src/web/Canvas.tsx 中,Canvas 首次渲染时会执行extend(THREE as any),把整个 THREE 命名空间注册进 JSX 元素目录(catalogue),之后所有 three 类型都可以直接以 JSX 标签使用;用户也可以通过extend把自己的自定义类注册为 JSX 元素。这也是"新特性即时可用"的底层原因——目录是动态、运行时构建的。

它长什么样:从零构建可交互 3D 组件

README 用一张动图和一段代码展示了核心体验:一个自带状态、响应鼠标输入、参与渲染循环的可复用组件

Web(JSX)示例

import { createRoot } from 'react-dom/client' import React, { useRef, useState } from 'react' import { Canvas, useFrame } from '@react-three/fiber' function Box(props) { // This reference gives us direct access to the THREE.Mesh object const ref = useRef() // Hold state for hovered and clicked events const [hovered, hover] = useState(false) const [clicked, click] = useState(false) // Subscribe this component to the render-loop, rotate the mesh every frame useFrame((state, delta) => (ref.current.rotation.x += delta)) // Return the view, these are regular Threejs elements expressed in JSX return ( <mesh {...props} ref={ref} scale={clicked ? 1.5 : 1} onClick={(event) => click(!clicked)} onPointerOver={(event) => hover(true)} onPointerOut={(event) => hover(false)}> <boxGeometry args={[1, 1, 1]} /> <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} /> </mesh> ) } createRoot(document.getElementById('root')).render( <Canvas> <ambientLight intensity={Math.PI / 2} /> <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} decay={0} intensity={Math.PI} /> <pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} /> <Box position={[-1.2, 0, 0]} /> <Box position={[1.2, 0, 0]} /> </Canvas>, )

逐段拆解这段"麻雀虽小五脏俱全"的示例:

  • useRef()拿到 Three.js 实例ref直接指向底层的THREE.Mesh对象,这是操作原生 three 对象的标准通道;
  • useState()承载交互状态hovered(悬停)与clicked(点击)驱动颜色与缩放变化;
  • useFrame((state, delta) => ...)订阅渲染循环:每一帧执行回调,delta是距上一帧的时间差,用它做旋转动画可保证不同帧率下速度一致;
  • JSX 事件绑定onClickonPointerOveronPointerOut直接写在元素上,与 DOM 事件写法一致;
  • 构造参数用args传入<boxGeometry args={[1, 1, 1]} />等价于new THREE.BoxGeometry(1, 1, 1)
  • props 即属性position={[10, 10, 10]}angle={0.15}intensity={Math.PI}等会直接应用到对应 three 实例上。

useFrame 的底层实现

从源码看,useFrame的核心逻辑位于 packages/fiber/src/core/hooks.tsx:

export function useFrame(callback: RenderCallback, renderPriority: number = 0): null { const store = useStore() const subscribe = store.getState().internal.subscribe const ref = useMutableCallback(callback) useIsomorphicLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]) return null }

它通过useStore()拿到 Canvas 的全局 Store,把回调注册进internal.subscribers订阅列表;组件卸载时自动取消订阅。renderPriority参数值得一提:默认0表示"只订阅更新逻辑、渲染仍由 R3F 自动驱动";若传入正数(如useFrame(cb, 1)),则该组件会接管渲染优先级——订阅者按优先级从低到高排序、最高优先级最后渲染,同时内部自动渲染会被暂停(见 packages/fiber/src/core/store.ts 中internal.priority的手动标志位逻辑),这一机制常用于实现"后处理覆盖层"等需要自定义渲染顺序的场景。

TypeScript 示例

安装类型后即可获得完整的类型提示与检查:

npm install @types/three
import * as THREE from 'three' import { createRoot } from 'react-dom/client' import React, { useRef, useState } from 'react' import { Canvas, useFrame, ThreeElements } from '@react-three/fiber' function Box(props: ThreeElements['mesh']) { const ref = useRef<THREE.Mesh>(null!) const [hovered, hover] = useState(false) const [clicked, click] = useState(false) useFrame((state, delta) => (ref.current.rotation.x += delta)) return ( <mesh {...props} ref={ref} scale={clicked ? 1.5 : 1} onClick={(event) => click(!clicked)} onPointerOver={(event) => hover(true)} onPointerOut={(event) => hover(false)}> <boxGeometry args={[1, 1, 1]} /> <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} /> </mesh> ) } createRoot(document.getElementById('root') as HTMLElement).render( <Canvas> <ambientLight intensity={Math.PI / 2} /> <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} decay={0} intensity={Math.PI} /> <pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} /> <Box position={[-1.2, 0, 0]} /> <Box position={[1.2, 0, 0]} /> </Canvas>, )

关键差异点:

  • ThreeElements['mesh']提供 JSX 元素的 props 类型(ThreeElements是 R3F 导出的元素类型映射);
  • useRef<THREE.Mesh>(null!)显式声明 ref 指向原生 Mesh 实例;
  • 事件回调、几何体、材质全部享受 TypeScript 推导。

React Native 示例

同样的代码可以跑在 React Native 上,只需把导入路径换成@react-three/fiber/native。该示例基于 React 18 与expo-cli(也可用 RN 模板或react-nativeCLI 创建裸项目):

# Install expo-cli, this will create our app npm install expo-cli -g # Create app and cd into it expo init my-app cd my-app # Install dependencies npm install three @react-three/fiber@beta react@rc # Start expo start

如果使用useLoader或 Drei 的useGLTFuseTexture等抽象加载资源,可能需要配置 Metro 打包器来识别资产文件:

// metro.config.js module.exports = { resolver: { sourceExts: ['js', 'jsx', 'json', 'ts', 'tsx', 'cjs'], assetExts: ['glb', 'png', 'jpg'], }, }

Native 端组件与 Web 端几乎一致(useFrame订阅渲染循环、onClick/onPointerOver/onPointerOut交互、args构造参数),唯一区别是入口组件与导入路径。从仓库结构看,Native 支持由 packages/fiber/src/native/Canvas.tsx 与 packages/fiber/src/native/events.ts 提供,@react-three/fiber/native的入口在 packages/fiber/src/native.tsx,Web 入口则在 packages/fiber/src/index.tsx,二者共享同一套 core(reconciler、store、hooks、loop),这正是"一次编写、两端运行"的架构基础。

开始前的准备:First Steps

README 提醒,上手 R3F 前你需要同时熟悉 React 与 Three.js。建议按以下顺序学习:

  1. 掌握 Three.js 基础:理解 scene(场景)、camera(相机)、mesh(网格)、geometry(几何体)、material(材质)这几个核心概念;
  2. 对照学习:理解了基础概念后,动手改造上文示例中的<mesh /><ambientLight />等 JSX 元素——Three.js 的所有导出对 three-fiber 都是原生可用的
  3. 查阅 API:尝试修改参数,翻阅官方 API 文档了解各个设置项与 Hooks 的作用;
  4. 推荐资料:Three.js 官方文档与示例、Discover Three.js 的 Tips and Tricks 章节、Bruno Simon 的 Three.js Journey 课程(其内容包含专门的 R3F 章节)都是不错的学习资源。

核心 API 与工作原理速览

Canvas:一切的入口

<Canvas>是最顶层的组件,它负责创建 WebGL 渲染器、场景、相机与渲染循环。从 packages/fiber/src/web/Canvas.tsx 可以看到它实际渲染的结构:外层 div(position: relative; width/height: 100%)内嵌测量容器与<canvas>元素。它使用react-use-measure自动测量父容器尺寸并响应 resize,因此Canvas 的父元素必须拥有确定的宽高,这是新手最常见的"黑屏"原因。

关键配置项(Canvas props)

结合 packages/fiber/src/core/renderer.tsx 中RenderProps的定义,常用配置如下:

配置项类型说明
glRenderer \| 函数 \| 部分 WebGLRenderer 属性自定义渲染器实例,或传入构造默认渲染器的属性(如{ antialias: true }
shadowsboolean \| 'basic' \| 'percentage' \| 'soft' \| 'variance' \| 部分属性启用阴影,默认 PCFSoft,可传字符串或gl.shadowMap选项细调
dprnumber \| [min, max]目标像素比,可用数组限定范围(如[1, 2])实现高分屏适配
frameloop'always' \| 'demand' \| 'never'渲染模式:始终渲染 / 仅在状态变化时按需渲染 / 完全手动控制
camera相机实例或属性对象可传{ fov, near, far, position }manual: true手动接管投影
orthographicboolean使用正交相机而非默认透视相机
legacy/linear/flatboolean分别用于关闭 r139 颜色管理、关闭 sRGB 编码与伽马校正、改用NoToneMapping
performancePartial<Performance>自适应性能参数(minmaxdebounce等)
raycaster/scene/events各种自定义 Raycaster / Scene / 事件管理器
onCreated(state) => void画布渲染完成(尚未提交)后的回调,常在此处访问state
onPointerMissed(event) => void点击未命中任何对象时的回调

Store:响应式的内部状态

R3F 的内部状态(RootState)是一个基于zustand的响应式 Store,字段定义在 packages/fiber/src/core/store.ts,主要包括:

  • glTHREE.WebGLRenderer实例;
  • camerasceneraycasterclock:默认相机、场景、射线拾取器与时钟;
  • size:画布响应式像素尺寸(widthheighttopleft);
  • viewport:Three.js 世界单位下的视口尺寸(含factordistanceaspect,以及按相机/目标点/尺寸重新计算的getCurrentViewport());
  • pointer:归一化后的指针坐标(mouse为弃用别名);
  • frameloopperformance:渲染模式与自适应性能;
  • invalidate()/advance():手动请求重绘 / 手动推进一帧(frameloop='demand''never'模式下配合使用)。

常用 Hooks

  • useThree(selector, equalityFn):以选择器读取 Store 状态,如const { gl, camera } = useThree()
  • useFrame(cb, priority):订阅渲染循环(见上文源码分析);
  • useLoader(Loader, input, extensions?, onProgress?):基于 Suspense 同步加载并缓存资源,useLoader.preload可预加载、useLoader.clear可清理缓存(见 packages/fiber/src/core/hooks.tsx);
  • useGraph(object):从已加载对象构建nodes/materials命名图(GLTF 场景常用);
  • useStore():获取 zustand Store 本身,适合做瞬时更新;
  • useInstanceHandle(ref):访问元素的底层 R3F Instance(react 内部字段的逃生舱口,注意跨版本可能变化)。

生态与使用案例

README 展示了围绕 three-fiber 形成的庞大生态,此处列举与本主题最直接相关的一批(均为社区项目,可自行检索):

  • 场景增强@react-three/drei(实用辅助组件集合,本身即是一个生态)、@react-three/gltfjsx(把 GLTF 转成 JSX 组件)、@react-three/postprocessing(后处理特效);
  • 交互与 UI@react-three/uikit(WebGL 渲染的 UI 组件)、@react-three/flex(flexbox 布局)、@react-three/a11y(无障碍)、use-gesture(鼠标/触摸手势)、leva(GUI 调试面板)、triplex(可视化编辑器);
  • 物理与渲染@react-three/rapier@react-three/cannon@react-three/p2(3D/3D/2D 物理)、@react-three/gpu-pathtracer(路径追踪)、lamina(分层着色器材质);
  • XR 与离屏@react-three/xr(VR/AR 控制器与事件)、@react-three/offscreen(worker 离屏画布)、@react-three/test-renderer(Node 环境单元测试,仓库内实现见 packages/test-renderer);
  • 状态与动画zustandjotaivaltio(三种状态管理风格)、react-spring(弹簧物理动画)、framer-motion-3d
  • 工程化create-r3f-app next(Next.js 启动模板)、maath(数学工具)、miniplex(ECS 实体管理)、composer-suite(着色器/粒子/游戏机制组合)。

在实际生产中,react-three-fiber 已被设计机构(如 vercel、basement studio、studio freight、14 islands、ueno)、PCB 设计工具(flux.ai)、3D 建模器(colorful.app、bezi)、头像配置器(readyplayer.me)、房产平台(zillow)、AI 模型与天空盒生成(lumalabs.ai/genie、skybox.blockadelabs)、CAD 软件(buerli.io、getencube、glowbuzzer)以及编辑器(triplex、theatrejs)等大量项目采用。

小结

react-three-fiber 的价值在于:它把 Three.js 庞大的命令式 API 折叠进 React 的声明式组件模型,让你用熟悉的 JSX、Hooks 与状态管理就能构建高性能、可维护的 3D 应用。记住三个要点即可快速上手:

  1. 版本配对:v9 配对 React 19、Three.js ≥ 0.156,安装前先核对;
  2. 一切皆组件<mesh /><boxGeometry /><ambientLight />就是 three 对象的 JSX 表达,args传构造参数、props 即属性、on*即事件;
  3. 从 Canvas 开始:给<Canvas>一个确定尺寸的父容器,用useFrame驱动动画、用useThree访问全局状态、用useLoader配合 Suspense 加载资源,即可逐步构建完整的 3D 应用。

【免费下载链接】react-three-fiber🇨🇭 A React renderer for Three.js项目地址: https://gitcode.com/GitHub_Trending/re/react-three-fiber

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 7:27:06

软件缺陷预测组合模型:加权投票与Stacking融合实战

简介&#xff1a;本资源是一套基于Python实现的组合机器学习软件缺陷预测模型实训项目&#xff0c;面向计算机相关专业本科生、研究生及教学科研人员&#xff0c;适用于毕业设计、课程设计与缺陷预测方向的算法实践。项目融合SVM、LR、RF、XGBoost、AdaBoost、MLP、Naive Bayes…

作者头像 李华
网站建设 2026/9/11 7:25:27

AutoHedge:面向AI智能体协同的分布式共识协议栈

1. AutoHedge不是“自动对冲”&#xff0c;而是智能体协同决策的底层范式重构AutoHedge这个词&#xff0c;最近在Solana开发者频道、AI Agent技术群和量化基础设施讨论组里高频出现&#xff0c;但绝大多数人一听到就下意识联想到“自动对冲交易系统”——这恰恰是它最危险的误解…

作者头像 李华
网站建设 2026/9/11 7:25:16

32GB显存跑56GB大模型:量化与异构内存架构实战解析

昨天群里有人问&#xff0c;朋友手里一张 32GB 显存的卡&#xff0c;想跑一个权重大小 56GB 的大模型文件&#xff0c;是不是只能换 40GB 或者 80GB 的卡&#xff1f;我说不一定&#xff0c;但也不能天真地以为“完全免费”。这个问题的核心&#xff0c;不是“显存能不能装下”…

作者头像 李华
网站建设 2026/9/11 7:22:37

Java空气质量监测管理系统解析:从Spring Boot到AQI计算

简介&#xff1a;面向Java学习者及环境监测项目开发者&#xff0c;这套空气质量监测信息管理系统源码包提供了一个前后端完整的参考实现。系统涵盖数据采集、数据库存储、前端展示等典型模块&#xff0c;有助于快速理解基于Java Web的分层架构与前后端交互逻辑&#xff0c;也适…

作者头像 李华
网站建设 2026/9/11 7:20:07

K8s网络深度解析:从容器网络到Service负载均衡排障实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 7:17:59

STM32宠物喂食系统:嵌入式实时控制与可靠性设计

简介&#xff1a;本资源是一套基于STM32F103的宠物智能喂食系统完整嵌入式项目代码&#xff0c;面向具备C语言与STM32基础的工程师及高校学生&#xff0c;聚焦物联网终端设备开发实践&#xff0c;解决宠物远程监控与定时/触发式自动喂食的实际问题。压缩包共39个文件&#xff0…

作者头像 李华