大白話react第十六章React 與 WebGL 結合的實戰項目

大白話react第十六章React 與 WebGL 結合的實戰項目

1. 項目簡介

React 是一個構建用戶界面的強大庫,而 WebGL 則允許我們在網頁上實現高性能的 3D 圖形渲染。將它們結合起來,我們可以創建出炫酷的 3D 網頁應用,比如 3D 產品展示、虛擬場景游覽等。接下來,我們會詳細介紹如何搭建這樣一個項目。

2. 項目搭建

首先,我們需要創建一個新的 React 項目,然后安裝相關的 WebGL 庫。這里我們使用 three.js,它是一個流行的 WebGL 抽象庫,能讓我們更方便地創建 3D 場景。

# 創建一個新的 React 項目
npx create-react-app react-webgl-project
cd react-webgl-project# 安裝 three.js 庫
npm install three
3. 創建 3D 場景組件

在 React 中,我們將創建一個組件來渲染 3D 場景。以下是一個簡單的示例:

// 引入 React 庫
import React, { useRef, useEffect } from'react';
// 引入 three.js 庫
import * as THREE from 'three';// 定義一個名為 ThreeScene 的 React 組件
const ThreeScene = () => {// 使用 useRef 創建一個 ref 對象,用于引用 DOM 元素const sceneRef = useRef();useEffect(() => {// 創建一個新的場景const scene = new THREE.Scene();// 創建一個透視相機,設置視角、寬高比、近裁剪面和遠裁剪面const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 將相機沿 z 軸向后移動 5 個單位camera.position.z = 5;// 創建一個 WebGL 渲染器const renderer = new THREE.WebGLRenderer();// 設置渲染器的大小為窗口的寬度和高度renderer.setSize(window.innerWidth, window.innerHeight);// 將渲染器的 DOM 元素添加到我們之前創建的 ref 對應的 DOM 元素中sceneRef.current.appendChild(renderer.domElement);// 創建一個立方體幾何體const geometry = new THREE.BoxGeometry();// 創建一個基本材質,顏色為藍色const material = new THREE.MeshBasicMaterial({ color: 0x0000ff });// 創建一個網格對象,將幾何體和材質組合在一起const cube = new THREE.Mesh(geometry, material);// 將立方體添加到場景中scene.add(cube);// 定義一個渲染函數,用于更新場景const animate = () => {// 請求瀏覽器在下一次重繪之前調用 animate 函數,實現動畫循環requestAnimationFrame(animate);// 讓立方體繞 x 軸和 y 軸旋轉cube.rotation.x += 0.01;cube.rotation.y += 0.01;// 使用渲染器渲染場景和相機renderer.render(scene, camera);};// 調用 animate 函數開始動畫animate();// 組件卸載時的清理函數return () => {// 移除渲染器的 DOM 元素sceneRef.current.removeChild(renderer.domElement);};}, []);return (// 創建一個 div 元素,用于容納 3D 場景,使用 ref 關聯到 sceneRef<div ref={sceneRef} />);
};export default ThreeScene;
4. 在 App 組件中使用 3D 場景組件

現在我們已經有了一個 3D 場景組件,接下來我們要在 App 組件中使用它。

// 引入 React 庫
import React from 'react';
// 引入我們之前創建的 ThreeScene 組件
import ThreeScene from './ThreeScene';// 定義 App 組件
const App = () => {return (<div>{/* 使用 ThreeScene 組件 */}<ThreeScene /></div>);
};export default App;
5. 優化與擴展

為了讓項目更完善,我們可以做一些優化和擴展,比如處理窗口大小變化、添加交互功能等。

// 引入 React 庫
import React, { useRef, useEffect } from'react';
// 引入 three.js 庫
import * as THREE from 'three';// 定義一個名為 ThreeScene 的 React 組件
const ThreeScene = () => {// 使用 useRef 創建一個 ref 對象,用于引用 DOM 元素const sceneRef = useRef();// 定義相機和渲染器的變量let camera;let renderer;useEffect(() => {// 創建一個新的場景const scene = new THREE.Scene();// 創建一個透視相機,設置視角、寬高比、近裁剪面和遠裁剪面camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 將相機沿 z 軸向后移動 5 個單位camera.position.z = 5;// 創建一個 WebGL 渲染器renderer = new THREE.WebGLRenderer();// 設置渲染器的大小為窗口的寬度和高度renderer.setSize(window.innerWidth, window.innerHeight);// 將渲染器的 DOM 元素添加到我們之前創建的 ref 對應的 DOM 元素中sceneRef.current.appendChild(renderer.domElement);// 創建一個立方體幾何體const geometry = new THREE.BoxGeometry();// 創建一個基本材質,顏色為藍色const material = new THREE.MeshBasicMaterial({ color: 0x0000ff });// 創建一個網格對象,將幾何體和材質組合在一起const cube = new THREE.Mesh(geometry, material);// 將立方體添加到場景中scene.add(cube);// 定義一個渲染函數,用于更新場景const animate = () => {// 請求瀏覽器在下一次重繪之前調用 animate 函數,實現動畫循環requestAnimationFrame(animate);// 讓立方體繞 x 軸和 y 軸旋轉cube.rotation.x += 0.01;cube.rotation.y += 0.01;// 使用渲染器渲染場景和相機renderer.render(scene, camera);};// 調用 animate 函數開始動畫animate();// 處理窗口大小變化的函數const handleResize = () => {// 更新相機的寬高比camera.aspect = window.innerWidth / window.innerHeight;// 更新相機的投影矩陣camera.updateProjectionMatrix();// 更新渲染器的大小renderer.setSize(window.innerWidth, window.innerHeight);};// 監聽窗口大小變化事件,調用 handleResize 函數window.addEventListener('resize', handleResize);// 組件卸載時的清理函數return () => {// 移除渲染器的 DOM 元素sceneRef.current.removeChild(renderer.domElement);// 移除窗口大小變化事件的監聽window.removeEventListener('resize', handleResize);};}, []);return (// 創建一個 div 元素,用于容納 3D 場景,使用 ref 關聯到 sceneRef<div ref={sceneRef} />);
};export default ThreeScene;
6. 總結

通過以上步驟,我們成功地將 React 和 WebGL 結合起來,創建了一個簡單的 3D 場景。在實際項目中,我們可以進一步擴展這個項目,比如添加更多的 3D 模型、光照效果、交互功能等,讓項目更加豐富和有趣。

在實戰項目中,如何使用React與WebGL進行交互?

1. 理解 React 與 WebGL 交互的基本思路

React 是用來構建用戶界面的,而 WebGL 能在網頁上實現 3D 圖形渲染。把它們結合起來,就是想用 React 來管理界面和交互邏輯,同時用 WebGL 來渲染 3D 場景。就好比 React 是指揮官,告訴 WebGL 什么時候該做什么,WebGL 則是干活的工人,負責把 3D 效果呈現出來。

2. 項目準備

首先得創建一個 React 項目,然后安裝 three.js 這個 WebGL 庫,它能讓我們更輕松地操作 WebGL。

# 創建一個新的 React 項目
npx create-react-app react-webgl-project
cd react-webgl-project# 安裝 three.js 庫
npm install three

3. 創建 React 組件與 WebGL 交互

下面是一個簡單的示例,展示了如何在 React 組件里使用 WebGL 渲染一個旋轉的立方體。

// 引入 React 相關的庫,useRef 用于引用 DOM 元素,useEffect 用于處理副作用
import React, { useRef, useEffect } from'react';
// 引入 three.js 庫,它是一個強大的 WebGL 抽象庫
import * as THREE from 'three';// 定義一個名為 WebGLScene 的 React 組件
const WebGLScene = () => {// 創建一個 ref 對象,用于引用 DOM 元素,之后會把 WebGL 渲染的內容放到這個元素里const sceneRef = useRef();useEffect(() => {// 創建一個新的 THREE 場景,這就像是一個舞臺,3D 物體都會放在這個舞臺上const scene = new THREE.Scene();// 創建一個透視相機,就像我們的眼睛,決定了我們從什么角度看 3D 場景// 75 是視角,window.innerWidth / window.innerHeight 是寬高比,0.1 和 1000 分別是近裁剪面和遠裁剪面const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 把相機往后移 5 個單位,這樣就能看到場景里的物體了camera.position.z = 5;// 創建一個 WebGL 渲染器,它負責把 3D 場景渲染成我們能看到的圖像const renderer = new THREE.WebGLRenderer();// 設置渲染器的大小為瀏覽器窗口的大小renderer.setSize(window.innerWidth, window.innerHeight);// 把渲染器生成的 DOM 元素添加到之前創建的 ref 對應的 DOM 元素中sceneRef.current.appendChild(renderer.domElement);// 創建一個立方體的幾何體,也就是立方體的形狀const geometry = new THREE.BoxGeometry();// 創建一個基本材質,給立方體一個藍色的外觀const material = new THREE.MeshBasicMaterial({ color: 0x0000ff });// 把幾何體和材質組合成一個網格對象,這就是我們要渲染的立方體const cube = new THREE.Mesh(geometry, material);// 把立方體添加到場景中scene.add(cube);// 定義一個動畫函數,用于更新場景并渲染const animate = () => {// 請求瀏覽器在下一次重繪之前調用 animate 函數,形成動畫循環requestAnimationFrame(animate);// 讓立方體繞 x 軸和 y 軸旋轉,這樣就能看到它在動了cube.rotation.x += 0.01;cube.rotation.y += 0.01;// 使用渲染器渲染場景和相機所看到的內容renderer.render(scene, camera);};// 調用動畫函數,開始動畫animate();// 組件卸載時的清理函數return () => {// 移除渲染器的 DOM 元素,避免內存泄漏sceneRef.current.removeChild(renderer.domElement);};}, []);return (// 創建一個 div 元素,用 ref 關聯到之前創建的 ref 對象,用于容納 WebGL 渲染的內容<div ref={sceneRef} />);
};export default WebGLScene;

4. 在 App 組件中使用 WebGL 組件

創建好 WebGL 組件后,要在 App 組件里使用它。

// 引入 React 庫
import React from 'react';
// 引入我們剛剛創建的 WebGLScene 組件
import WebGLScene from './WebGLScene';// 定義 App 組件
const App = () => {return (<div>{/* 使用 WebGLScene 組件,這樣就能在頁面上看到 WebGL 渲染的 3D 場景了 */}<WebGLScene /></div>);
};export default App;

5. 處理交互

在實際項目中,我們可能需要處理用戶的交互,比如點擊、拖動等。下面是一個簡單的示例,實現點擊立方體改變顏色的功能。

// 引入 React 相關的庫,useRef 用于引用 DOM 元素,useEffect 用于處理副作用,useState 用于管理狀態
import React, { useRef, useEffect, useState } from'react';
import * as THREE from 'three';
// 引入 three.js 的射線投射器,用于檢測點擊事件
import { Raycaster, Vector2 } from 'three';const WebGLScene = () => {const sceneRef = useRef();// 定義一個狀態變量,用于存儲立方體的顏色const [cubeColor, setCubeColor] = useState(0x0000ff);useEffect(() => {const scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.z = 5;const renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);sceneRef.current.appendChild(renderer.domElement);// 創建一個立方體的幾何體const geometry = new THREE.BoxGeometry();// 使用狀態變量 cubeColor 來設置立方體的顏色const material = new THREE.MeshBasicMaterial({ color: cubeColor });const cube = new THREE.Mesh(geometry, material);scene.add(cube);// 創建一個射線投射器,用于檢測點擊事件const raycaster = new Raycaster();// 創建一個二維向量,用于存儲鼠標的位置const mouse = new Vector2();// 處理鼠標點擊事件的函數const handleClick = (event) => {// 計算鼠標在標準化設備坐標中的位置mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;// 使用射線投射器從相機位置沿著鼠標方向發射一條射線raycaster.setFromCamera(mouse, camera);// 檢測射線與場景中的物體是否相交const intersects = raycaster.intersectObjects(scene.children);// 如果射線與立方體相交if (intersects.length > 0 && intersects[0].object === cube) {// 隨機生成一個新的顏色const newColor = Math.random() * 0xffffff;// 更新狀態變量 cubeColorsetCubeColor(newColor);// 更新立方體的材質顏色cube.material.color.set(newColor);}};// 監聽鼠標點擊事件window.addEventListener('click', handleClick);const animate = () => {requestAnimationFrame(animate);cube.rotation.x += 0.01;cube.rotation.y += 0.01;renderer.render(scene, camera);};animate();return () => {sceneRef.current.removeChild(renderer.domElement);// 移除鼠標點擊事件的監聽,避免內存泄漏window.removeEventListener('click', handleClick);};}, [cubeColor]);return (<div ref={sceneRef} />);
};export default WebGLScene;

總結

通過以上步驟,我們就實現了 React 與 WebGL 的交互。先是創建了一個基本的 3D 場景,然后在 React 組件里管理這個場景,最后還實現了簡單的交互功能。在實際項目中,你可以根據需求進一步擴展,比如添加更多的 3D 模型、復雜的光照效果等。

除了three.js,還有哪些WebGL庫可以與React結合使用?

除了 three.js,能和 React 結合用的 WebGL 庫

在做網頁的 3D 效果時,除了大家常用的 three.js,還有不少其他的 WebGL 庫能和 React 搭配,下面就來詳細說說這些庫。

1. Babylon.js
  • 白話解釋:Babylon.js 就像是一個功能強大的 3D 游戲開發小工具包,它能讓你輕松地在網頁上創建出復雜又炫酷的 3D 場景,像做 3D 游戲、虛擬展覽這些都不在話下。
  • 代碼示例
// 引入 React 相關的庫
import React, { useRef, useEffect } from'react';
// 引入 Babylon.js 庫
import * as BABYLON from 'babylonjs';// 創建一個名為 BabylonScene 的 React 組件
const BabylonScene = () => {// 創建一個 ref 對象,用來關聯后續的 DOM 元素const canvasRef = useRef(null);useEffect(() => {// 獲取 ref 對應的 DOM 元素,這里是畫布const canvas = canvasRef.current;// 創建一個 Babylon.js 的引擎,基于這個畫布const engine = new BABYLON.Engine(canvas, true);// 創建一個新的 3D 場景const scene = new BABYLON.Scene(engine);// 創建一個相機,讓用戶可以觀察場景const camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 2, 2, BABYLON.Vector3.Zero(), scene);// 讓相機可以被鼠標控制camera.attachControl(canvas, true);// 創建一個光源,照亮場景const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);// 創建一個球體,作為場景中的物體const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 1 }, scene);// 定義一個渲染循環函數const renderLoop = () => {// 渲染場景scene.render();};// 啟動渲染循環engine.runRenderLoop(renderLoop);// 監聽窗口大小變化,調整畫布大小window.addEventListener('resize', () => {engine.resize();});// 組件卸載時的清理操作return () => {// 停止渲染循環engine.stopRenderLoop(renderLoop);// 釋放引擎資源engine.dispose();};}, []);return (// 創建一個畫布元素,使用 ref 關聯到 canvasRef<canvas ref={canvasRef} style={{ width: '100%', height: '500px' }} />);
};export default BabylonScene;
2. PlayCanvas
  • 白話解釋:PlayCanvas 就像是一個在線的 3D 創作平臺,它有自己的可視化編輯器,就算你不太懂代碼,也能做出好看的 3D 項目。而且它和 React 結合后,能讓你的網頁有很棒的 3D 效果。
  • 代碼示例
// 引入 React 相關的庫
import React, { useRef, useEffect } from'react';
// 引入 PlayCanvas 庫
import * as pc from 'playcanvas';// 創建一個名為 PlayCanvasScene 的 React 組件
const PlayCanvasScene = () => {// 創建一個 ref 對象,用來關聯后續的 DOM 元素const containerRef = useRef(null);useEffect(() => {// 獲取 ref 對應的 DOM 元素,作為容器const container = containerRef.current;// 創建一個 PlayCanvas 的應用實例const app = new pc.Application(container, {graphicsDeviceOptions: {alpha: true}});// 設置應用的分辨率和填充模式app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);app.setCanvasResolution(pc.RESOLUTION_AUTO);// 啟用統計信息顯示app.start();// 創建一個實體,作為相機const camera = new pc.Entity('camera');// 給相機添加相機組件camera.addComponent('camera', {clearColor: new pc.Color(0.1, 0.1, 0.1)});// 設置相機的位置camera.setPosition(0, 0, 3);// 將相機添加到場景中app.root.addChild(camera);// 創建一個實體,作為立方體const cube = new pc.Entity('cube');// 給立方體添加模型組件cube.addComponent('model', {type:'box'});// 將立方體添加到場景中app.root.addChild(cube);// 定義一個更新函數,用于更新場景const update = () => {// 讓立方體繞 y 軸旋轉cube.rotate(0, 1, 0);};// 監聽應用的更新事件,調用 update 函數app.on('update', update);// 組件卸載時的清理操作return () => {// 停止應用app.stop();// 移除應用的 DOM 元素container.innerHTML = '';};}, []);return (// 創建一個 div 元素,作為容器,使用 ref 關聯到 containerRef<div ref={containerRef} style={{ width: '100%', height: '500px' }} />);
};export default PlayCanvasScene;
3. PixiJS
  • 白話解釋:PixiJS 主要是用來做 2D 圖形和動畫的,但它也支持 WebGL 加速,能讓 2D 畫面又快又好看。和 React 結合后,能在網頁上做出超棒的 2D 交互效果。
  • 代碼示例
// 引入 React 相關的庫
import React, { useRef, useEffect } from'react';
// 引入 PixiJS 庫
import * as PIXI from 'pixi.js';// 創建一個名為 PixiScene 的 React 組件
const PixiScene = () => {// 創建一個 ref 對象,用來關聯后續的 DOM 元素const appRef = useRef(null);useEffect(() => {// 創建一個 PixiJS 的應用實例const app = new PIXI.Application({width: 800,height: 600,backgroundColor: 0x1099bb});// 獲取 ref 對應的 DOM 元素,將應用的視圖添加進去appRef.current.appendChild(app.view);// 創建一個圓形圖形const circle = new PIXI.Graphics();circle.beginFill(0xFF0000);circle.drawCircle(0, 0, 50);circle.endFill();// 設置圓形的位置circle.x = 400;circle.y = 300;// 將圓形添加到舞臺上app.stage.addChild(circle);// 定義一個動畫函數,用于更新圓形的位置const animate = () => {// 讓圓形在 x 軸上移動circle.x += 1;if (circle.x > 800) {circle.x = 0;}// 請求下一幀動畫requestAnimationFrame(animate);};// 啟動動畫animate();// 組件卸載時的清理操作return () => {// 銷毀應用app.destroy(true);// 移除應用的視圖appRef.current.removeChild(app.view);};}, []);return (// 創建一個 div 元素,作為容器,使用 ref 關聯到 appRef<div ref={appRef} />);
};export default PixiScene;

這些庫各有各的特點,你可以根據項目的需求來選擇合適的庫和 React 結合使用,做出更酷炫的網頁效果。

如何優化React與WebGL結合的項目性能?

如何優化 React 與 WebGL 結合的項目性能

1. 減少不必要的渲染

在 React 里,組件可能會因為各種原因頻繁重新渲染,這會影響性能。我們可以用 React.memo 來避免組件的不必要渲染。對于 WebGL 場景,渲染循環也可能會產生不必要的繪制,我們要合理控制渲染時機。

// 引入 React 相關的庫,包括 React.memo 和 useEffect
import React, { memo, useEffect, useRef } from'react';
// 引入 three.js 庫,這里以 three.js 為例,其他 WebGL 庫思路類似
import * as THREE from 'three';// 使用 React.memo 包裹組件,只有當 props 改變時才重新渲染
const OptimizedWebGLComponent = memo((props) => {// 創建一個 ref 來引用 DOM 元素,后續用于掛載 WebGL 渲染器const containerRef = useRef(null);useEffect(() => {// 創建一個新的 THREE 場景const scene = new THREE.Scene();// 創建一個透視相機,設置視角、寬高比、近裁剪面和遠裁剪面const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 創建一個 WebGL 渲染器const renderer = new THREE.WebGLRenderer();// 設置渲染器的大小為窗口的寬度和高度renderer.setSize(window.innerWidth, window.innerHeight);// 將渲染器的 DOM 元素添加到我們之前創建的 ref 對應的 DOM 元素中containerRef.current.appendChild(renderer.domElement);// 創建一個立方體幾何體const geometry = new THREE.BoxGeometry();// 創建一個基本材質,顏色為藍色const material = new THREE.MeshBasicMaterial({ color: 0x0000ff });// 創建一個網格對象,將幾何體和材質組合在一起const cube = new THREE.Mesh(geometry, material);// 將立方體添加到場景中scene.add(cube);// 將相機沿 z 軸向后移動 5 個單位camera.position.z = 5;// 定義一個渲染函數const animate = () => {// 請求瀏覽器在下一次重繪之前調用 animate 函數,實現動畫循環requestAnimationFrame(animate);// 讓立方體繞 x 軸和 y 軸旋轉cube.rotation.x += 0.01;cube.rotation.y += 0.01;// 使用渲染器渲染場景和相機renderer.render(scene, camera);};// 調用 animate 函數開始動畫animate();// 組件卸載時的清理函數return () => {// 移除渲染器的 DOM 元素containerRef.current.removeChild(renderer.domElement);};}, []);return (// 創建一個 div 元素,用于容納 WebGL 場景,使用 ref 關聯到 containerRef<div ref={containerRef} />);
});export default OptimizedWebGLComponent;
2. 優化 WebGL 場景
  • 減少幾何體的復雜度:復雜的幾何體需要更多的計算資源來渲染。可以簡化模型,比如用簡單的形狀代替復雜的模型。
  • 合并幾何體:如果場景中有多個相似的幾何體,可以把它們合并成一個,減少繪制調用的次數。
// 引入 React 相關的庫,包括 useEffect 和 useRef
import React, { useEffect, useRef } from'react';
import * as THREE from 'three';const OptimizedGeometryComponent = () => {const containerRef = useRef(null);useEffect(() => {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);containerRef.current.appendChild(renderer.domElement);// 創建一個簡單的平面幾何體,相比復雜模型更節省資源const geometry = new THREE.PlaneGeometry(5, 5);const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });const plane = new THREE.Mesh(geometry, material);scene.add(plane);camera.position.z = 5;const animate = () => {requestAnimationFrame(animate);renderer.render(scene, camera);};animate();return () => {containerRef.current.removeChild(renderer.domElement);};}, []);return (<div ref={containerRef} />);
};export default OptimizedGeometryComponent;
3. 合理使用紋理
  • 壓縮紋理:大尺寸的紋理會占用大量內存,使用圖像編輯工具對紋理進行壓縮,在不影響視覺效果的前提下減小文件大小。
  • 按需加載紋理:只有當需要顯示某個紋理時才加載它,避免一次性加載過多紋理。
// 引入 React 相關的庫,包括 useEffect 和 useRef
import React, { useEffect, useRef } from'react';
import * as THREE from 'three';const TextureOptimizedComponent = () => {const containerRef = useRef(null);useEffect(() => {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);containerRef.current.appendChild(renderer.domElement);// 創建一個紋理加載器const textureLoader = new THREE.TextureLoader();// 加載一個壓縮后的紋理圖片textureLoader.load('compressed_texture.jpg', (texture) => {const geometry = new THREE.BoxGeometry();// 使用加載的紋理創建材質const material = new THREE.MeshBasicMaterial({ map: texture });const cube = new THREE.Mesh(geometry, material);scene.add(cube);});camera.position.z = 5;const animate = () => {requestAnimationFrame(animate);renderer.render(scene, camera);};animate();return () => {containerRef.current.removeChild(renderer.domElement);};}, []);return (<div ref={containerRef} />);
};export default TextureOptimizedComponent;
4. 管理渲染循環
  • 控制幀率:不需要一直以最高幀率渲染,可以根據實際需求降低幀率,減少 CPU 和 GPU 的負擔。
  • 暫停不必要的渲染:當場景不可見或者用戶沒有交互時,暫停渲染循環。
// 引入 React 相關的庫,包括 useEffect、useRef 和 useState
import React, { useEffect, useRef, useState } from'react';
import * as THREE from 'three';const RenderLoopOptimizedComponent = () => {const containerRef = useRef(null);// 使用 useState 來控制是否渲染const [isRendering, setIsRendering] = useState(true);useEffect(() => {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);containerRef.current.appendChild(renderer.domElement);const geometry = new THREE.BoxGeometry();const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });const cube = new THREE.Mesh(geometry, material);scene.add(cube);camera.position.z = 5;// 定義一個渲染函數const animate = () => {if (isRendering) {// 請求瀏覽器在下一次重繪之前調用 animate 函數,實現動畫循環requestAnimationFrame(animate);cube.rotation.x += 0.01;cube.rotation.y += 0.01;renderer.render(scene, camera);}};animate();return () => {containerRef.current.removeChild(renderer.domElement);};}, [isRendering]);return (<div><div ref={containerRef} />{/* 添加一個按鈕來控制是否渲染 */}<button onClick={() => setIsRendering(!isRendering)}>{isRendering? '暫停渲染' : '開始渲染'}</button></div>);
};export default RenderLoopOptimizedComponent;

通過以上這些方法,我們可以顯著提升 React 與 WebGL 結合項目的性能,讓應用運行得更加流暢。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/72674.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/72674.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/72674.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【AI賦能】AI 工具生成視頻教材:從創意到成品的全流程指南

AI 工具生成視頻教材&#xff1a;從創意到成品的全流程指南 目標 通過本教材&#xff0c;您將學會如何利用 AI 工具&#xff08;Grok、Sora、Speechify 和 CapCut&#xff09;生成一個完整的視頻&#xff0c;包括腳本生成、視頻片段制作、字幕添加、音頻生成以及最終剪輯合成…

C/C++藍橋杯算法真題打卡(Day2)

一、面試題 08.01. 三步問題 - 力扣&#xff08;LeetCode&#xff09; 算法代碼&#xff1a; class Solution { public:const int MOD 1e9 7;int waysToStep(int n) {// 1. 創建 dp 表// 2. 初始化// 3. 填表// 4. 返回// 處理邊界情況if (n 1 || n 2)return n;if (n 3)r…

騰訊云物聯網平臺(IoT Explorer)設備端使用

1、直接看圖流程 2、跑起來demo,修改產品id,設備名稱,設備秘鑰。 3、連接部分 4、修改默認地址和端口 sdk里面的地址默認是帶著產品ID拼接的,咱們現在中鐵沒有泛域名解析,要改下這里。把+productID都去掉,然后地址里的.也去掉。

GStreamer —— 2.13、Windows下Qt加載GStreamer庫后運行 - “教程13:播放控制“(附:完整源碼)

運行效果(音頻) 簡介 上一個教程演示了GStreamer工具。本教程介紹視頻播放控制。快進、反向播放和慢動作都是技術 統稱為 Trick Modes&#xff0c;它們都有一個共同點 修改 Normal playback rate。本教程介紹如何實現 這些效果并在交易中添加了幀步進。特別是&#xff0c;它 顯…

Dify+DeepSeek | Excel數據一鍵可視化(創建步驟案例)(echarts助手.yml)(文檔表格轉圖表、根據表格繪制圖表、Excel繪制圖表)

Dify部署參考&#xff1a;Dify Rag部署并集成在線Deepseek教程&#xff08;Windows、部署Rag、安裝Ragan安裝、安裝Dify安裝、安裝ollama安裝&#xff09; DifyDeepSeek - Excel數據一鍵可視化&#xff08;創建步驟案例&#xff09;-DSL工程文件&#xff08;可直接導入&#x…

vscode mac版本 配置git

首先使用 type -a git查看git的安裝目錄 然后在vscode中找到settings配置文件&#xff0c;修改git.path

JVM與性能調優詳解

以下是關于 JVM與性能調優 的詳細解析&#xff0c;結合理論、實踐及常見問題&#xff0c;分多個維度展開&#xff1a; 一、JVM性能調優的核心目標 性能調優的核心目標是通過優化內存管理、垃圾回收&#xff08;GC&#xff09;策略和線程管理&#xff0c;實現以下平衡&#xff…

Vue23Web 基礎性拉滿的面試題(2025版)還沒更新完...

Vue2&3 基礎性1. 關於Vue2和Vue3生命週期的差別2. Vue2&3組件之間傳參不同點Vue2 傳遞與接收Vue3 傳遞與接收 (使用script setup語法糖)Vue3 傳遞與接收 (不使用script setup語法糖) 3. Vue2&3 keep-alive 組件Vue2 keep-aliveVue3 keep-alive 進階性爲什麼POST請求…

基于SpringBoot實現旅游酒店平臺功能一

一、前言介紹&#xff1a; 1.1 項目摘要 隨著社會的快速發展和人民生活水平的不斷提高&#xff0c;旅游已經成為人們休閑娛樂的重要方式之一。人們越來越注重生活的品質和精神文化的追求&#xff0c;旅游需求呈現出爆發式增長。這種增長不僅體現在旅游人數的增加上&#xff0…

【程序自動分析——并查集,離散化】

題目 代碼&#xff08;注意不是把p修改為unordered_map&#xff0c;而是增加一個get&#xff09; #include <bits/stdc.h> using namespace std;const int N 2e510; //n個數據&#xff0c;可能引入2*n個離散點int p[N]; bool cannot; unordered_map<int, int> mp…

審批流AntV框架螞蟻數據可視化X6餅圖(附注釋)

大家好&#xff0c;這次使用的是AntV的螞蟻數據可視化X6框架&#xff0c;類似于審批流的場景等&#xff0c;代碼如下&#xff1a; X6框架參考網址&#xff1a;https://x6.antv.vision/zh/examples/showcase/practices#bpmn 可以進入該網址&#xff0c;直接復制下方代碼進行調試…

linux取代ls的命令行工具:eza

官方倉庫 https://github.com/eza-community/eza 安裝 cargo install eza驗證 eza --version用法 替換ls 別名 安裝文檔 官方提供的安裝文檔是這個 https://github.com/eza-community/eza/blob/main/INSTALL.md 可以通過cargo命令安裝&#xff0c;debian還可以通過apt安裝…

【DeepSeek】Ubuntu快速部署DeepSeek(Ollama方式)

文章目錄 人人都該學習的DeepSeekDeepSeek不同版本功能差異DeepSeek與硬件直接的關系DeepSeek系統兼容性部署方式選擇部署步驟&#xff08;Ollama方式&#xff09;1.選定適合的deepseek版本2.環境準備3.安裝Ollama4.部署deepseek5.測試使用 人人都該學習的DeepSeek DeepSeek 作…

redis熱key

在 Redis 中&#xff0c;熱 Key&#xff08;Hot Key&#xff09; 是指被頻繁訪問的 Key&#xff0c;可能會導致以下問題&#xff1a; 性能瓶頸&#xff1a;單個 Redis 實例的 CPU 或網絡帶寬被耗盡。 數據傾斜&#xff1a;在 Redis 集群中&#xff0c;熱 Key 可能導致某個節點…

宇樹科技嵌入式面試題及參考答案(春晚機器人的公司)

目錄 設計一個帶看門狗(Watchdog)的嵌入式系統,描述故障恢復流程 在資源受限的 MCU 上實現 OTA 升級功能,描述關鍵設計點 如何實現 OTA(空中升級)功能?描述固件校驗和回滾機制的設計要點 推挽輸出與開漏輸出的區別?舉例說明其在 GPIO 控制中的應用 UART、SPI、I2C …

Axure常用變量及使用方法詳解

點擊下載《Axure常用變量及使用方法詳解.pdf》 摘要 Axure RP 作為一款領先的前端原型設計工具&#xff0c;提供了全面的 變量 和 函數 系統&#xff0c;以支持復雜的交互設計和動態內容展示。本文將從專業角度詳細解析 Axure 中的 全局變量、中繼器數據集變量/函數、元件變量…

SpringBoot - 用責任鏈模式實現業務編排

文章目錄 前因責任鏈&#xff1a;像工作臺一樣組織代碼CodeSEQ3.1 定義處理器規范3.2 實現具體處理器3.3 共享上下文3.4 組裝責任鏈 適用場景優勢 前因 2000多行的業務邏輯里&#xff0c;各種校驗規則、促銷計算、庫存操作像意大利面條一樣纏繞在一起。最要命的是這樣的代碼結…

upload-labs詳解(13-20)文件上傳分析

目錄 upload-labs-env upload-labs-env第十三關 文件包含漏洞 代碼 測試 上傳一個.jpg圖片 上傳一個.png文件 上傳一個.gif圖片 upload-labs-env第十四關 代碼 思路 upload-labs-env第十五關 代碼 思路 upload-labs-env第十六關 代碼 思路 測試 上傳gif格式…

網絡安全通信架構圖

&#x1f345; 點擊文末小卡片 &#xff0c;免費獲取網絡安全全套資料&#xff0c;資料在手&#xff0c;漲薪更快 在安全通信里面我經常聽到的2個東西就是SSL和TLS&#xff0c;這2個有什么區別呢&#xff1f;以及HTTPS是怎么通信的&#xff1f;包括對稱加密、非對稱加密、摘要、…

Java中的String類

目錄 1. String類的重要性 2. 常用方法 2.1 字符串構造 2.2 String對象的比較 2.3 字符串查找 2.4 轉化 2.5 字符串替換 2.6 字符串拆分 2.7 字符串截取 2.8 其他操作方法 2.9 字符串的不可變性 2.10 字符串修改 3. StringBuilder和StringBuffer 3.1 StringBuilde…