You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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的创建和生命周期,不用手动操作DOM
  • useFrame用来处理动画逻辑,参数里还能拿到当前时钟、相机状态等信息
  • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 07:59:05