使用 react-three-fiber 深入 React 和 Three.js

已發表: 2022-03-10
快速總結 ↬ react-three-fiber是一個強大的 Three.js 渲染器,可以幫助渲染 React 及其原生應用程序的 3D 模型和動畫。 在本教程中,您將學習如何在 React 應用程序中配置和構建 3D 模型。

今天,我們將學習如何配置和使用react-three-fiber在 React 和 React Native 應用程序中構建和顯示 3D 模型和動畫。

本教程適用於想要了解更多關於使用 React 的 Web 中的 3D 模型動畫的開發人員,以及任何對 Three.js 有限制(例如無法創建畫布、綁定用戶事件(如click事件)和啟動渲染循環、 react-three-fiber )的人react-three-fiber帶有這些方法。 我們將構建一個 3D 模型,以更好地了解如何使用react-three-fiber構建 Three.js 3D 模型。

react-three-fiber入門

Three.js 是一個可以更輕鬆地在瀏覽器中創建 3D 圖形的庫,它使用畫布 + WebGL 來顯示 3D 模型和動畫,您可以在此處了解更多信息。

react-three-fiber 是 web 上 Three.js 和 react-native 的 React 渲染器,它提高了使用 Three.js 創建 3D 模型和動畫的速度,一些具有 3D 模型和動畫的網站示例可以在這裡找到。 react-three-fiber減少了在動畫上花費的時間,因為它具有可重用的組件、綁定事件和渲染循環,首先我們來看看 Three.js 是什麼。

react-three-fiber允許我們使用 React 狀態、鉤子和道具構建threeJS代碼的組件,它還帶有以下元素:

元素描述
mesh 有助於定義模型形狀的屬性
hooks react-three-fiber定義了幫助我們編寫函數來幫助定義用戶事件的鉤子,例如onClickonPointOver
基於組件和渲染循環react-three-fiber是基於組件的,根據狀態或存儲的變化進行渲染
跳躍後更多! 繼續往下看↓

如何使用react-three-fiber

要使用react-three-fiber ,首先使用以下命令:

新PM

 npm i three react-three-fiber

yarn add three react-three-fiber

注意要讓react-three-fiber工作,你需要像我們上面那樣安裝three (Three.js)。

構建 React 3D Ludo Dice 模型和動畫項目

在這裡,我們將使用react-three-fiber構建一個 3D 骰子模型,就像我們在下面的視頻中一樣。

我們將使用create-react-app來初始化我們的項目,為此讓我們在終端上執行以下命令。

 create-react-app react-three-fiber-ludo-model

上面的命令在我們的本地機器中初始化了一個 React 項目,接下來讓我們cd進入目錄並安裝我們的包react-three-fiberthree

 cd react-three-fiber-ludo-model npm i three react-three-fiber

一旦安裝了軟件包,讓我們使用命令啟動我們的開發服務器

npm start

上面的命令應該在我們的瀏覽器中啟動我們的項目開發服務器。 接下來讓我們在我們選擇的文本編輯器中打開我們的項目,在我們的項目src文件夾中,刪除以下文件: App.cssApp.test.jsserviceWorker.jssetupTests.js 。 接下來,讓我們刪除所有引用App.js上已刪除文件的代碼。

對於這個項目,我們將需要一個Box組件用於我們的 Ludo 骰子和由 React 提供的App組件。

構建Box組件

Box組件將包含我們的ludo 骰子的形狀、ludo 骰子的圖像和始終保持旋轉的狀態。 首先,讓我們為下面的Box組件導入我們需要的所有包。

 import React, { useRef, useState, useMemo } from "react"; import { Canvas, useFrame } from "react-three-fiber"; import * as THREE from "three"; import five from "./assets/five.png";

在上面的代碼中,我們導入useRefuseStateuseMemo 。 我們將使用useRef鉤子來訪問骰子的網格,並使用useState鉤子來檢查 ludo 骰子的活動狀態。 useMemo鉤子將用於返回骰子上的數字。 接下來,我們從react-three-fiber導入CanvasuseFramecanvas用於在瀏覽器上繪製圖形,而useFrame允許組件掛鉤到渲染循環,這使得一個組件可以渲染另一個的內容。 接下來,我們導入了這three包,然後我們導入了一個盧多骰子的靜態圖像。

接下來是為我們的Box組件編寫邏輯。 首先,我們將從構建一個功能組件開始,並為我們的組件添加狀態,讓我們在下面這樣做。

 const Box = (props) => { const mesh = useRef(); const [active, setActive] = useState(false); useFrame(() => { mesh.current.rotation.x = mesh.current.rotation.y += 0.01; }); const texture = useMemo(() => new THREE.TextureLoader().load(five), []); return ( <Box /> ); }

在上面的代碼中,我們創建了一個帶有 props 的Box組件,接下來我們使用useRef鉤子創建了一個名為mesh的引用,這樣做是為了每次都可以返回相同的網格。

網格是場景中的視覺元素,它是構成三角形多邊形的 3D 對象,它通常使用Geometry構建,用於定義模型的形狀, Material用於定義模型的外觀,您可以在此處了解 Mesh,您還可以在此處了解有關useRef掛鉤的更多信息。

初始化mesh後,我們需要使用useState鉤子為我們的應用程序初始化一個狀態,這裡我們將應用程序的懸停和活動狀態設置為 false。

接下來,我們使用react-three-fiber中的useFrame鉤子來旋轉網格(ludo dice),使用下面的代碼

mesh.current.rotation.x = mesh.current.rotation.y += 0.01;

在這裡,我們每 0.01 秒旋轉一次網格的當前位置,這樣做是為了給旋轉一個好的動畫。

 const texture = useMemo(() => new THREE.TextureLoader().load(five), []);

在上面的代碼中,我們創建了一個名為texture的常量,並傳入一個 react useMemo鉤子作為函數來加載一個新的擲骰子,這裡使用useMemo來記憶骰子圖像及其編號。 你可以在這裡了解useMemo鉤子。

接下來,我們要在瀏覽器上渲染Box組件並添加我們的事件,我們在下面這樣做

const Box = (props) => { return ( <mesh {...props} ref={mesh} scale={active ? [2, 2, 2] : [1.5, 1.5, 1.5]} onClick={(e) => setActive(!active)} > <boxBufferGeometry args={[1, 1, 1]} /> <meshBasicMaterial attach="material" transparent side={THREE.DoubleSide}> <primitive attach="map" object={texture} /> </meshBasicMaterial> </mesh> ); }

在上面的代碼中,我們返回了我們的Box組件並將其包裝在mesh中,我們使用擴展運算符傳遞了Box組件的所有屬性,然後我們使用useRef掛鉤引用了網格。 接下來,我們使用 Three.js 中的scale屬性來設置骰子框的大小,當它處於活動狀態時為 2 和 1.5,當它不處於活動狀態時。 最後但並非最不重要的一點是,我們添加了一個onClick事件以將state設置為active ,如果它未設置為默認值。

 <boxBufferGeometry args={[1, 1, 1]} />

為了渲染骰子盒子,我們從 Three.js 中渲染了boxBufferGeometry組件, boxBufferGeometry幫助我們繪製了諸如盒子之類的線和點,我們使用args參數來傳遞諸如盒子幾何尺寸之類的構造函數。

 <meshBasicMaterial attach="material" transparent side={THREE.DoubleSide}>

meshBasicMaterial中的 meshBasicMaterial 用於以簡單的形式繪製幾何圖形。 在這裡,我們傳遞了attach屬性並將THREE.DoubleSide道具傳遞給side屬性。 THREE.DoubleSide定義了應該由react-three-fiber渲染的邊或空間。

 <primitive attach="map" object={texture} />

Three.js 的primitive組件用於繪製 3D 圖形。 我們附加了 map 屬性以保持 Ludo 骰子的原始形狀。 接下來,我們將在App.js文件中渲染我們的Box組件並完成我們的 3d ludo 骰子框。 您的組件應該類似於下圖。

ludo 3D 盒子的盒子組件

渲染 3D Ludo 骰子盒

在本節中,我們將在App.js中渲染我們的Box組件並完成我們的 3d ludo 框,首先,讓我們創建一個App組件並用Canvas標籤包裝它,這是為了渲染我們的 3D 模型,讓我們在下面這樣做。

 const App = () => { return ( <Canvas> </Canvas> ); } export default App;

接下來,讓我們為盒子添加一個燈光, react-three-fiber為我們提供了三個組件來點亮我們的模型,它們如下

  • ambientLight
    這用於均勻地照亮場景或模型中的所有對象,它接受諸如光強度之類的道具,這將照亮盧多骰子的主體。
  • spotLight
    這種光是從一個方向發出的,它隨著物體大小的增加而增加,這將照亮盧多骰子的點。
  • pointLight
    這類似於燈泡的光,光從一個點發射到各個方向,這對於我們的應用程序的活動狀態是必要的。

讓我們在下面的應用程序中實現上述內容。

 const App = () => { return ( <Canvas> <ambientLight intensity={0.5} /> <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} /> <pointLight position={[-10, -10, -10]} /> </Canvas> ); } export default App;

在上面的代碼中,我們從react-three-fiber導入了環境光組件,並pointLight添加了 0.5 的強度,接下來我們為我們的spotLightambientLight組件添加了位置和角度。 我們應用程序的最後一步是渲染我們的盒子組件並為 ludo 骰子盒子添加一個位置,我們將在下面的代碼中這樣做

<Box position={[-1.2, 0, 0]} /> <Box position={[2.5, 0, 0]} />

完成後,您的 Ludo 3D 骰子應類似於下圖:

3D盧多骰子盒

CodeSandbox 上提供了一個工作演示。

結論

react-three-fiber使得渲染 3D 模型和動畫更容易為 React 和 React Native 應用程序創建。 通過構建我們的 3D 骰子盒,我們了解了 Three.js 的基礎知識以及react-three-fiber的組件和優點以及如何使用它。

您可以通過自己使用react-three-fiber在您的 React 和 Native 應用程序中構建 3D 模型和動畫來進一步實現這一點。 我很想看看你想出了什麼新東西!

您可以在下面的參考資料中閱讀有關 Three.js 和react-three-fiber的更多信息。

相關資源

  • 三.js 文檔
  • 三.js 基礎
  • Poimandres 的 React-Three-Fiber GitHub 存儲庫
  • 反應三纖維文檔
  • React Hooks(useState、useMemo等)官方文檔