React+React Three Fiber多Mesh条件渲染优化方案咨询
解决方案
核心思路
用单个状态变量替代12个布尔值,通过循环批量渲染mesh,控制材质/可见性实现显示隐藏,既避免代码冗余又能保留ref。
1. 简化状态管理
不再为每个选项单独创建状态,改用activeMeshId变量:
- 值为
null时:显示所有mesh - 值为具体ID(1-12)时:仅显示对应ID的mesh
- 点击侧边栏选项时,若当前选中的是该ID则重置为
null,否则设置为该ID
// App.js import { useState } from 'react'; import ConvexHull from './ConvexHull'; function App() { const [activeMeshId, setActiveMeshId] = useState(null); const handleOptionClick = (id) => { setActiveMeshId(prev => prev === id ? null : id); }; return ( <div> {/* 侧边栏 */} <div className="sidebar"> {[...Array(12).keys()].map(i => { const id = i + 1; return ( <button key={id} onClick={() => handleOptionClick(id)} className={activeMeshId === id ? 'active' : ''} > 选项 {id} </button> ); })} </div> <ConvexHull activeMeshId={activeMeshId} /> </div> ); } export default App;
2. 批量渲染Mesh组件
将12个mesh的配置统一管理,通过循环渲染避免重复代码,同时用数组存储所有ref,确保每个mesh的ref都能正确保留。
// ConvexHull.js import { useRef } from 'react'; import { motion } from 'framer-motion'; function ConvexHull({ activeMeshId }) { // 存储所有mesh的ref const convexRefs = useRef([]); // 定义材质动画变体(替换成你自己的var1/var2逻辑) const materialVariants = { visible: { opacity: 1, transition: { duration: 0.3 } }, hidden: { opacity: 0, transition: { duration: 0.3 } } }; return ( <> {[...Array(12).keys()].map(i => { const meshId = i + 1; // 判断当前mesh是否需要显示 const isVisible = activeMeshId === null || activeMeshId === meshId; return ( <mesh key={meshId} ref={el => convexRefs.current[i] = el} // 可选:如果需要完全禁用交互,加上visible属性 visible={isVisible} > {/* 替换成你的实际geometry */} <boxGeometry /> <motion.meshBasicMaterial initial="visible" animate={isVisible ? "visible" : "hidden"} variants={materialVariants} /> </mesh> ); })} </> ); } export default ConvexHull;
3. 关键细节说明
- 避免ref丢失:不通过返回
null隐藏mesh,而是通过控制材质的opacity或mesh的visible属性,确保mesh始终存在于场景中,ref不会丢失。 - 动画兼容:如果你的
var1/var2有更复杂的动画(比如颜色变化、缩放),直接替换materialVariants的内容即可,逻辑完全兼容。 - 扩展性:后续如果需要增加更多mesh,只需要修改数组长度,无需额外添加状态或重复代码。
内容的提问来源于stack exchange,提问作者黃紹齊
相关产品推荐
相关产品推荐

