⚡Three.js-R3F,在React工程项目中使用Three.js


theme: scrolls-light
highlight: atom-one-dark

本文正在参加「金石计划 . 瓜分6万现金大奖」

Demo地址:r3f-demo

在之前的几篇的文章中,我们介绍了一些Three.js的基本用法:

  1. ⚡初识Three.js,在场景中创建一个旋转的正方体~
  2. ⚡Three.js-在场景中导入3D动画模型

假设现在你已经学会了所有的Three.js基本使用方法,已经能够创建简单场景,在场景中添加动画,灯光,阴影等,但是我们想在工程项目中集成Three.js,我推荐@react-three/fiber@react-three/drei。这个是业界在React工程项目中使用Three.js比较成熟的解决方案。

react-three-fiber is a React renderer for threejs.

react-three-drei is a growing collection of useful helpers and fully functional, ready-made abstractions for @react-three/fiber.

今天这篇文章就带大家学习使用它们,你会发现,oh,amazing!
项目目录结构:

image.png

1. 使用r3f创建场景

// App.js
import { Canvas } from "@react-three/fiber";

export default function App() {
  return (
    <Wrapper className="App">
      <Canvas className="canvas">
      </Canvas>
    </Wrapper>
  );
}

2. 在场景中创建正方体

// ./components/Box.js
import React from "react";

export default function Box() {
  return (
    <mesh>
      <boxBufferGeometry attach="geometry" />
      <MeshLambertMaterial attach="material" />
    </mesh>
  );
}
// App.js
import Box from "./components/Box";

import { Canvas } from "@react-three/fiber";

export default function App() {
  return (
    <Wrapper className="App">
      <Canvas className="canvas">
          <Box />
      </Canvas>
    </Wrapper>
  );
}

image.png
现在我们就成功地在场景中添加了正方体,但是它非常小,并且是黑色的,我们需要做出一些调整。
首先我们的canvas高度比较小,我们调整一下它的高度

canvas {
    height: 500px;
}

如何更改正方体的大小?

我们只需要在boxBufferGeometry添加args属性即可,args的属性值是一个数组,我们填入[3,3,3]即将正方体的长宽高设置为3。

    <mesh>
      <boxBufferGeometry attach="geometry" args={[3, 3, 3]}/>
      <meshNormalMaterial attach="material" />
    </mesh>

image.png

image.png

现在看起来可能更像正方形,我们尝试给正方体添加一些旋转角度。在mesh上添加rotation={[90, 0, 20]即可

    <mesh rotation={[90, 0, 20]}>
      <boxBufferGeometry attach="geometry" args={[3, 3, 3]}/>
      <MeshLambertMaterial attach="material" />
    </mesh>

image.png

现在我们得到了一个全黑的正方体,接下来,尝试在场景中添加一些灯光。

如何添加灯光?

灯光元素应该添加canvas元素内

  <Canvas className="canvas">
      <ambientLight intensity={0.5} />
      <directionalLight position={[-2, 5, 2]} intensity={1} />
  </Canvas>

position属性为光源的位置,intensity属性为光源的强度

image.png
现在我们可以清楚看到正方体的每一个边缘了。

我们还需要添加轨道控制器,接下来,我们尝试添加它,这时候我们需要从@react-three/drei中引入它。
然后在canvas元素中添加它,其中enableZoom属性的作用是控制是否可以缩放。

import { OrbitControls } from "@react-three/drei";
  <Canvas className="canvas">
      <OrbitControls enableZoom={false} />
      <ambientLight intensity={0.5} />
      <directionalLight position={[-2, 5, 2]} intensity={1} />
  </Canvas>

接下来我们尝试在正方体上添加纹理。

如何给正方体添加纹理?

我们需要使用r3f提供的一个加载器hook——useLoader

这里要注意,我们需要将meshmaterial调整一下,将其调整为meshStandardMaterial

import React from "react";

import { useLoader } from "@react-three/fiber";
import { TextureLoader } from "three/src/loaders/TextureLoader";
import texture from "../images/map.jpg";

export default function Box() {
  const colorMap = useLoader(TextureLoader, texture);

  return (
    <mesh rotation={[90, 0, 20]}>
      <boxBufferGeometry attach="geometry" args={[3, 3, 3]} />
      <meshStandardMaterial attach="material" />
    </mesh>
  );
}

这时候,你会发现有报错

image.png
提示你需要添加一个Suspense,这是因为我们使用useLoader时,无法获取到material,然后就会报错,现在我们添加Suspense

// App.js
import React, { Suspense } from "react";
import Box from "./components/Box";

import { Canvas } from "@react-three/fiber";

export default function App() {
  return (
    <Wrapper className="App">
      <Canvas className="canvas">
        <OrbitControls enableZoom={false} />
        <ambientLight intensity={0.5} />
        <directionalLight position={[-2, 5, 2]} intensity={1} />
        <Suspense fallback={null}>
          <Box />
        </Suspense>
      </Canvas>
    </Wrapper>
  );
}

image.png
现在就成功地将纹理添加到正方体上了。

3. 在场景中导入3D模型

这次我们选择在Sketchfab上去找模型

image.png

我们挑一条鲨鱼啊,然后下载模型,当然我们应该选择gltf格式,因为它对网站性能很好,不会减慢你的网站速度。

image.png

下载之后,我们需要借助gltf-pipeline将glTF 1.0 models 转换为 glTF 2.0

image.png
执行下面两个命令:

npm install -g gltf-pipeline
gltf-pipeline -i scene.gltf -o shark.gltf

image.png

现在我们得到了shark.gltf文件,我们现在需要使用gltfjsx这个库,将我们的gltf文件转换为jsx component

执行下面的命令:

npx gltfjsx shark.gltf

我这里执行命令,失败了

image.png
提示在node中Fetch是一个实验性的功能,由于我的node用的是19.0.0,我们这里需要降级,这里降到14.17.6,然后继续执行上述命令即可

image.png

现在我们得到了shark.js

接着我们在App.js中引入即可

import React, { Suspense } from "react";
import "./styles.css";
import styled from "styled-components";

import Box from "./components/Box";
import Shark from "./components/Shark";

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

export default function App() {
  return (
    <Wrapper className="App">
      <Canvas className="canvas">
        <OrbitControls enableZoom={false} />
        <ambientLight intensity={0.5} />
        <directionalLight position={[-2, 5, 2]} intensity={1} />
        <Suspense fallback={null}>
          <Box />
        </Suspense>
      </Canvas>
      <Canvas className="canvas">
        <OrbitControls enableZoom={false} />
        <ambientLight intensity={0.5} />
        <directionalLight position={[-2, 5, 2]} intensity={1} />
        <Suspense fallback={null}>
          <Shark />
        </Suspense>
      </Canvas>
    </Wrapper>
  );
}

1111.png

现在就成功导入我们big shark啦,关于R3F的更多细节可参考

  • https://github.com/pmndrs/react-three-fiber#Ecosystem

最后

⚾如果你对本专栏感兴趣欢迎点赞关注+收藏,后面会持续更新,更多精彩知识正在等你!😘
🏉此外笔者还有其他专栏,欢迎阅读~
🏐玩转CSS之美
🎳深入浅出JavaScript

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容