You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在多立方体场景中动态修改React-three-fiber Line组件的顶点?

解决方案

不用状态管理也能实现线条顶点的动态更新,核心思路是直接操作Three.js的几何体实例,结合ref来获取立方体和线条的对象:

步骤1:管理立方体和线条的Ref

用useRef创建数组存储所有立方体的mesh实例,同时单独存储线条的ref:

import { useRef, useEffect } from 'react';
import { useFrame } from '@react-three/fiber';
import { Line, TransformControls } from '@react-three/drei';

function Scene() {
  const cubeRefs = useRef([]); // 存储所有立方体的mesh实例
  const lineRef = useRef(); // 存储线条实例

  // 假设cubes是动态生成的立方体数据,可从props传入
  const cubes = [{ color: 'red' }, { color: 'blue' }, { color: 'green' }];

步骤2:渲染立方体并绑定Ref

渲染每个立方体时,将其mesh实例存入cubeRefs.current数组:

return (
    <>
      {cubes.map((cube, index) => (
        <mesh
          key={index}
          ref={(el) => cubeRefs.current[index] = el}
          position={[index * 2, 0, 0]}
        >
          <boxGeometry args={[1, 1, 1]} />
          <meshStandardMaterial color={cube.color} />
          <TransformControls object={cubeRefs.current[index]} />
        </mesh>
      ))}

步骤3:实时更新线条顶点

有两种实现方式,按需选择:

方式一:帧循环实时更新(适合高频变化场景)

用useFrame在每一帧检查立方体位置并更新线条:

useFrame(() => {
    // 至少需要2个立方体才生成线条
    if (cubeRefs.current.length >= 2) {
      // 收集所有立方体的位置
      const positions = cubeRefs.current.map(cube => {
        const { x, y, z } = cube.position;
        return [x, y, z];
      });

      if (lineRef.current) {
        // 更新线条的几何体顶点
        lineRef.current.geometry.setFromPoints(
          positions.map(p => new THREE.Vector3(...p))
        );
        // 标记几何体需要更新,Three.js才会重新渲染
        lineRef.current.geometry.verticesNeedUpdate = true;
        lineRef.current.geometry.computeBoundingSphere();
      }
    }
  });

方式二:监听位置变化事件(性能更优)

给每个立方体的position对象添加change事件,仅在位置变化时更新线条:

useEffect(() => {
    const updateLine = () => {
      if (cubeRefs.current.length >= 2) {
        const positions = cubeRefs.current.map(cube => {
          const { x, y, z } = cube.position;
          return new THREE.Vector3(x, y, z);
        });

        if (lineRef.current) {
          lineRef.current.geometry.setFromPoints(positions);
          lineRef.current.geometry.verticesNeedUpdate = true;
          lineRef.current.geometry.computeBoundingSphere();
        }
      }
    };

    // 给每个立方体绑定位置变化监听
    cubeRefs.current.forEach(cube => {
      cube.position.addEventListener('change', updateLine);
    });

    // 组件卸载时清理监听
    return () => {
      cubeRefs.current.forEach(cube => {
        cube.position.removeEventListener('change', updateLine);
      });
    };
  }, [cubes.length]); // 立方体数量变化时重新绑定监听

步骤4:渲染线条

最后渲染线条组件并绑定ref:

<Line ref={lineRef} color="white" linewidth={2} />
    </>
  );
}

关键说明

  • 直接操作Three.js几何体可避免频繁的React状态更新和组件重渲染,适配动态数量的立方体场景
  • 必须设置verticesNeedUpdate = true,否则Three.js无法识别顶点变化
  • computeBoundingSphere可选,但能确保线条的碰撞检测和视锥体剔除正常工作

内容的提问来源于stack exchange,提问作者Samir Kumar Patro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 03:52:42