大白话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.mzph.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…