如何优雅的在React中使用Three.js

470 阅读4分钟

banner-r3f.jpg (1750×500) (raw.githubusercontent.com) 大家好!今天我们来聊聊在 React 中使用 Three.js 的那些“痛点”。如果你曾经尝试在 React 项目中使用 Three.js,你可能会发现自己被一堆 new 实例化搞得头晕目眩。每次都要写一大堆 new THREE.Scene()new THREE.Camera()new THREE.Mesh(),这简直是对 React 风格的“背叛”!React 是一个声明式的框架,而 Three.js 则是一个命令式的库,这两者的结合简直让人抓狂。今天来给同学们分享一个在React中很好用的一个关于threejs的插件库react-three-fiber。 好的,那我们来详细一些,增加一些更具体的示例,并介绍一下 react-three/drei 这个库。希望这次的分享能更全面地帮助大家在 React 中优雅地使用 Three.js。

如何在 React 中优雅地使用 React-Three-Fiber

开发团队介绍

幸运的是,有一群聪明的开发者看到了我们的痛苦,并决定拯救我们于水火之中。他们创建了一个叫做 React-Three-Fiber 的开源库,让我们可以在 React 中优雅地使用 Three.js。这群开发者可不是“无名之辈”,他们还开发了很多在 React 中经常用到的库,比如 React Spring(动画库)、Zustand(状态管理库)等等。这些库在 React 社区中都非常受欢迎,质量有保证。

使用 React-Three-Fiber

那么,React-Three-Fiber 到底是如何让我们优雅地使用 Three.js 的呢?让我们来看看一些示例代码吧。

示例代码对比

直接使用 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();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 5;

const animate = function () {
  requestAnimationFrame(animate);
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  renderer.render(scene, camera);
};

animate();

使用 React-Three-Fiber:

import React from 'react';
import { Canvas } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';

function Box() {
  return (
    <mesh rotation={[0.01, 0.01, 0]}>
      <boxGeometry args={[1, 1, 1]} />
      <meshBasicMaterial color="green" />
    </mesh>
  );
}

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

export default App;

看到了吗?使用 React-Three-Fiber 后,我们的代码变得多么简洁优雅!我们不再需要手动实例化各种对象,只需要像写 React 组件一样写 Three.js 的元素。

创建场景、相机和物体

让我们更详细地看看如何在 React-Three-Fiber 中创建场景、相机和物体。

创建场景和相机:

在 React-Three-Fiber 中,<Canvas> 组件相当于 Three.js 中的 scenerenderer。你可以在 <Canvas> 中直接添加各种 Three.js 元素,比如光源、相机和物体。

创建物体:

你可以使用各种 Three.js 的几何体和材质来创建物体。比如,创建一个立方体:

function Box() {
  return (
    <mesh position={[0, 0, 0]}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color="orange" />
    </mesh>
  );
}

使用相机:

默认情况下,React-Three-Fiber 会自动创建一个透视相机并将其放置在适当的位置。如果你需要自定义相机,可以使用 useThree 钩子来访问 Three.js 的上下文:

import { useThree } from '@react-three/fiber';

function CustomCamera() {
  const { camera } = useThree();
  camera.position.set(0, 0, 5);
  return null;
}

使用 React-Three-Drei

React-Three-Drei 是一个非常有用的辅助库,提供了很多常用的 Three.js 组件和工具,比如相机控制、加载器、灯光等。让我们看看如何使用它:

安装 React-Three-Drei:

npm install @react-three/drei

使用 OrbitControls:

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

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

OrbitControls 允许你使用鼠标控制相机,非常方便。

使用注意事项

当然,使用 React-Three-Fiber 也有一些需要注意的地方:

  1. 性能问题:虽然 React-Three-Fiber 让我们可以更方便地使用 Three.js,但它也可能带来一些性能问题。在复杂的场景中,确保合理使用 React 的 useMemouseCallback 来优化性能。
  2. 学习曲线:如果你对 Three.js 和 React 都不熟悉,可能需要花一些时间来适应 React-Three-Fiber 的用法。不过,一旦你掌握了它,你会发现它非常强大。
  3. 社区支持:React-Three-Fiber 有一个活跃的社区,遇到问题时可以随时求助。官方文档和示例也非常丰富,帮助你快速上手。

结尾

感谢大家的阅读!希望这篇文章能帮助你在 React 项目中优雅地使用 Three.js。如果你有任何问题或建议,欢迎在评论区指出。后续我还会更新更多关于 React 中使用 Three.js 的功能分享,敬请期待!

Happy coding! 🎉