资讯动态

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

发布时间:2026/9/11 7:27:34 来源:尧图企业网站定制
react-three-fiber 完全指南用 React 声明式渲染 Three.js 3D 场景【免费下载链接】react-three-fiber A React renderer for Three.js项目地址: https://gitcode.com/GitHub_Trending/re/react-three-fiberreact-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 对象树组件内部的useState、useRef、useFrame等让场景拥有自己的行为逻辑与 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/fiber8配对react18react-three/fiber9配对react19。本仓库中的 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 1919 19.3、Three.js0.156react-dom与react-native均为可选 peer 依赖这正是同一份代码可以同时跑在 Web 与 React Native 上的原因。安装前请务必检查你的 React 主版本避免渲染器与运行时版本错配导致的异常。常见疑问解答FAQREADME 用三个问答快速回应了开发者最常见的顾虑Q它有局限吗没有。凡是在 Three.js 中能工作的东西在这里都能工作无一例外。Q它比纯 Three.js 慢吗不慢。没有额外开销组件在 React 之外渲染。得益于 React 的调度能力它在规模上反而优于 Three.js。Q它能跟上 Three.js 频繁的版本更新吗能。它只是把 Three.js 表达为 JSXmesh /动态地变成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 用一张动图和一段代码展示了核心体验一个自带状态、响应鼠标输入、参与渲染循环的可复用组件。WebJSX示例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 事件绑定onClick、onPointerOver、onPointerOut直接写在元素上与 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.tsxexport 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/threeimport * 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 useRefTHREE.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 导出的元素类型映射useRefTHREE.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/fiberbeta reactrc # Start expo start如果使用useLoader或 Drei 的useGLTF、useTexture等抽象加载资源可能需要配置 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.tsxWeb 入口则在 packages/fiber/src/index.tsx二者共享同一套 corereconciler、store、hooks、loop这正是一次编写、两端运行的架构基础。开始前的准备First StepsREADME 提醒上手 R3F 前你需要同时熟悉 React 与 Three.js。建议按以下顺序学习掌握 Three.js 基础理解 scene场景、camera相机、mesh网格、geometry几何体、material材质这几个核心概念对照学习理解了基础概念后动手改造上文示例中的mesh /、ambientLight /等 JSX 元素——Three.js 的所有导出对 three-fiber 都是原生可用的查阅 API尝试修改参数翻阅官方 API 文档了解各个设置项与 Hooks 的作用推荐资料Three.js 官方文档与示例、Discover Three.js 的 Tips and Tricks 章节、Bruno Simon 的 Three.js Journey 课程其内容包含专门的 R3F 章节都是不错的学习资源。核心 API 与工作原理速览Canvas一切的入口Canvas是最顶层的组件它负责创建 WebGL 渲染器、场景、相机与渲染循环。从 packages/fiber/src/web/Canvas.tsx 可以看到它实际渲染的结构外层 divposition: 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]实现高分屏适配frameloopalways \| demand \| never渲染模式始终渲染 / 仅在状态变化时按需渲染 / 完全手动控制camera相机实例或属性对象可传{ fov, near, far, position }或manual: true手动接管投影orthographicboolean使用正交相机而非默认透视相机legacy/linear/flatboolean分别用于关闭 r139 颜色管理、关闭 sRGB 编码与伽马校正、改用NoToneMappingperformancePartialPerformance自适应性能参数min、max、debounce等raycaster/scene/events各种自定义 Raycaster / Scene / 事件管理器onCreated(state) void画布渲染完成尚未提交后的回调常在此处访问stateonPointerMissed(event) void点击未命中任何对象时的回调Store响应式的内部状态R3F 的内部状态RootState是一个基于zustand的响应式 Store字段定义在 packages/fiber/src/core/store.ts主要包括glTHREE.WebGLRenderer实例camera、scene、raycaster、clock默认相机、场景、射线拾取器与时钟size画布响应式像素尺寸width、height、top、leftviewportThree.js 世界单位下的视口尺寸含factor、distance、aspect以及按相机/目标点/尺寸重新计算的getCurrentViewport()pointer归一化后的指针坐标mouse为弃用别名frameloop、performance渲染模式与自适应性能invalidate()/advance()手动请求重绘 / 手动推进一帧frameloopdemand与never模式下配合使用。常用 HooksuseThree(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.tsxuseGraph(object)从已加载对象构建nodes/materials命名图GLTF 场景常用useStore()获取 zustand Store 本身适合做瞬时更新useInstanceHandle(ref)访问元素的底层 R3F Instancereact 内部字段的逃生舱口注意跨版本可能变化。生态与使用案例README 展示了围绕 three-fiber 形成的庞大生态此处列举与本主题最直接相关的一批均为社区项目可自行检索场景增强react-three/drei实用辅助组件集合本身即是一个生态、react-three/gltfjsx把 GLTF 转成 JSX 组件、react-three/postprocessing后处理特效交互与 UIreact-three/uikitWebGL 渲染的 UI 组件、react-three/flexflexbox 布局、react-three/a11y无障碍、use-gesture鼠标/触摸手势、levaGUI 调试面板、triplex可视化编辑器物理与渲染react-three/rapier、react-three/cannon、react-three/p23D/3D/2D 物理、react-three/gpu-pathtracer路径追踪、lamina分层着色器材质XR 与离屏react-three/xrVR/AR 控制器与事件、react-three/offscreenworker 离屏画布、react-three/test-rendererNode 环境单元测试仓库内实现见 packages/test-renderer状态与动画zustand、jotai、valtio三种状态管理风格、react-spring弹簧物理动画、framer-motion-3d工程化create-r3f-app nextNext.js 启动模板、maath数学工具、miniplexECS 实体管理、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 应用。记住三个要点即可快速上手版本配对v9 配对 React 19、Three.js ≥ 0.156安装前先核对一切皆组件mesh /、boxGeometry /、ambientLight /就是 three 对象的 JSX 表达args传构造参数、props 即属性、on*即事件从 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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价