如何将three.js集成到react-three-fiber中?
如何将Three.js代码与react-three-fiber结合
嘿,我来帮你理清怎么把原生Three.js代码和react-three-fiber(简称r3f)结合起来——你提到的标签正是r3f最核心的特性,它把Three.js的原生API直接映射成了React的JSX组件标签,用起来特别顺。下面一步步给你讲具体实现:
核心逻辑:Three.js 对象 ↔️ React JSX标签
r3f的核心设计就是把Three.js的所有类都转换成了小写开头的JSX标签,比如:
THREE.Mesh→<mesh>THREE.BoxGeometry→<boxGeometry>THREE.MeshBasicMaterial→<meshBasicMaterial>
标签的属性要么对应Three.js类的构造函数参数(用args数组传递),要么对应实例的属性(比如color、wireframe)。
具体实现步骤
1. 先搭好基础环境
首先确保你有React项目,然后安装依赖:
npm install three @react-three/fiber @react-three/drei
@react-three/drei是官方推荐的辅助组件库,封装了很多常用功能(比如模型加载、控制器),能省不少事,可选但非常推荐。
2. 把原生Three.js代码转成r3f组件
举个最常见的例子:原生Three.js写旋转立方体,转成r3f代码后会简洁很多。
原生Three.js版本:
import * as THREE from 'three'; // 手动初始化场景、相机、渲染器 const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 创建立方体 const geometry = new THREE.BoxGeometry(1,1,1); const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); const cube = new THREE.Mesh(geometry, material); scene.add(cube); camera.position.z = 5; // 手动写动画循环 function animate() { requestAnimationFrame(animate); cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render(scene, camera); } animate();
r3f版本:
import { Canvas, useFrame, useRef } from '@react-three/fiber'; // 立方体组件 function RotatingCube() { // 用useRef获取Three.js的mesh实例 const cubeRef = useRef(); // useFrame钩子替代原生的动画循环,每一帧都会执行 useFrame(() => { if (cubeRef.current) { cubeRef.current.rotation.x += 0.01; cubeRef.current.rotation.y += 0.01; } }); // 用JSX标签对应Three.js对象,args传递构造函数参数 return ( <mesh ref={cubeRef}> <boxGeometry args={[1, 1, 1]} /> <meshBasicMaterial color={0x00ff00} /> </mesh> ); } // 主组件 function App() { // <Canvas>组件自动帮你处理场景、相机、渲染器的初始化 return ( <Canvas camera={{ position: [0, 0, 5] }}> <RotatingCube /> </Canvas> ); } export default App;
这里要划几个重点:
<Canvas>是r3f的核心容器,自动封装了scene、renderer、camera的创建和生命周期,不用手动操作DOMuseFrame用来处理动画逻辑,参数里还能拿到当前时钟、相机状态等信息useRef用来获取Three.js的原生实例,就像原生代码里的cube变量
3. 处理复杂场景:自定义材质、加载模型
如果要做更复杂的事情,比如加载GLTF模型、写自定义着色器,r3f也能轻松搞定:
加载GLTF模型(用drei组件)
import { GLTF } from '@react-three/drei'; function LoadedModel() { return ( <GLTF src="/your-model.gltf"> {/* 可以直接在内部修改模型的材质、位置等 */} <meshStandardMaterial color="hotpink" attach="material" /> </GLTF> ); }
自定义着色器
import { useRef, useFrame } from '@react-three/fiber'; function CustomShaderCube() { const shaderRef = useRef(); // 每一帧更新着色器的uniform变量 useFrame((state) => { if (shaderRef.current) { shaderRef.current.uniforms.time.value = state.clock.elapsedTime; } }); return ( <mesh> <boxGeometry /> <shaderMaterial ref={shaderRef} uniforms={{ time: { value: 0 } }} vertexShader={` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `} fragmentShader={` uniform float time; varying vec2 vUv; void main() { gl_FragColor = vec4(vUv.x + sin(time), vUv.y + cos(time), 0.5, 1.0); } `} /> </mesh> ); }
4. 整合已有的原生Three.js代码
如果你有现成的Three.js逻辑不想重写,r3f也支持直接操作原生Three.js对象:
import { useThree, useFrame, useEffect, useRef } from '@react-three/fiber'; import * as THREE from 'three'; function NativeThreeIntegration() { // 用useThree获取原生的scene、camera等对象 const { scene } = useThree(); const sphereRef = useRef(); // 组件挂载时创建原生Three.js对象并添加到场景 useEffect(() => { const geometry = new THREE.SphereGeometry(1, 32, 32); const material = new THREE.MeshPhysicalMaterial({ color: 0x42a5f5 }); const sphere = new THREE.Mesh(geometry, material); sphereRef.current = sphere; scene.add(sphere); // 组件卸载时清理资源,避免内存泄漏 return () => { scene.remove(sphere); geometry.dispose(); material.dispose(); }; }, [scene]); // 用useFrame做动画 useFrame(() => { if (sphereRef.current) { sphereRef.current.rotation.z += 0.01; } }); // 因为是手动添加到scene,所以返回null return null; }
总结
r3f本质是把React的状态管理、生命周期和Three.js的渲染逻辑做了无缝结合:
- 用JSX标签替代原生Three.js的实例化代码,更符合React开发习惯
- 用
useFrame、useThree等钩子处理动画和原生对象操作 - 既能快速实现简单场景,也能完全兼容复杂的原生Three.js逻辑
内容的提问来源于stack exchange,提问作者Dan Glodeanu
相关产品推荐
相关产品推荐

