如何使用 React 和 Three.js 动态更改网格颜色

发布于 2025-01-15 03:00:33 字数 1390 浏览 2 评论 0原文

我知道这是一个微不足道的问题,但我向你保证我已经尝试解决这个问题几个小时了。 color 属性是一个字符串(例如 '#f56d3d'),它应该更改网格材质颜色。我正在使用 useEffect 来初始化场景,并尝试使用另一个来更改颜色。

function Scene({ color, shape }) {
  const cubeRef = useRef(null);

  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
  const renderer = new THREE.WebGLRenderer({ alpha: true });
  const geometry = new THREE.BoxGeometry();
  const material = new THREE.MeshBasicMaterial({ color });
  const cube = new THREE.Mesh(geometry, material);

  const animate = () => {
    requestAnimationFrame(animate);
    cube.material.color.setStyle(color);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
  };

  useEffect(() => {
    renderer.setSize(window.innerWidth,  window.innerHeight);
    cubeRef.current.appendChild(renderer.domElement);
    scene.add(cube);
    camera.position.z = 5;

    animate();
  },[]);

  return (
    <div ref={cubeRef}>
    </div>
  )
}

export default Scene

我想到的是一种让渲染器知道场景内的立方体已更改的方法。 到目前为止我尝试过的是:

  • cube.material.needsUpdate = true;
  • renderer.render(scene, camera);
  • cube.material = new 三。 MeshBasicMaterial({ 颜色 }); 所有这些都在 useEffect 中,以“color”为 dep。

谢谢

I know this is a trivial question but I assure you I've been trying to solve this for several hours.
The color prop is a string (e.g '#f56d3d') and it should change the mesh material color. I'm using useEffect to initialize the scene and I've tried to use another to change the color

function Scene({ color, shape }) {
  const cubeRef = useRef(null);

  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
  const renderer = new THREE.WebGLRenderer({ alpha: true });
  const geometry = new THREE.BoxGeometry();
  const material = new THREE.MeshBasicMaterial({ color });
  const cube = new THREE.Mesh(geometry, material);

  const animate = () => {
    requestAnimationFrame(animate);
    cube.material.color.setStyle(color);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
  };

  useEffect(() => {
    renderer.setSize(window.innerWidth,  window.innerHeight);
    cubeRef.current.appendChild(renderer.domElement);
    scene.add(cube);
    camera.position.z = 5;

    animate();
  },[]);

  return (
    <div ref={cubeRef}>
    </div>
  )
}

export default Scene

What comes to my mind is a way to let know the renderer that the cube inside the scene has changed.
What I've tried so far is:

  • cube.material.needsUpdate = true;
  • renderer.render(scene, camera);
  • cube.material = new THREE.MeshBasicMaterial({ color });
    All of these inside a useEffect with `color as dep.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

Spring初心 2025-01-22 03:00:33

如果您不介意创建一个新对象,那么您可以重新排列 useEffect 中的变量,如下所示:

  const cubeRef = useRef(null);
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
  const renderer = new THREE.WebGLRenderer({ alpha: true });
  const geometry = new THREE.BoxGeometry();
  let cube, material;
  
  const animate = () => {
    requestAnimationFrame(animate);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
  };

  useEffect(() => {
    material = new THREE.MeshBasicMaterial({color});
    cube = new THREE.Mesh(geometry, material);
    renderer.setSize(window.innerWidth,  window.innerHeight);
    cubeRef.current.innerHTML = '';
    cubeRef.current.appendChild(renderer.domElement);
    scene.add(cube);
    camera.position.z = 5;
    animate();
  }, [color])

此外,您可能需要将先前的定位或旋转保存在某处。

If you dont mind creating a new object then you can rearrange the variables in the useEffect like this:

  const cubeRef = useRef(null);
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
  const renderer = new THREE.WebGLRenderer({ alpha: true });
  const geometry = new THREE.BoxGeometry();
  let cube, material;
  
  const animate = () => {
    requestAnimationFrame(animate);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
  };

  useEffect(() => {
    material = new THREE.MeshBasicMaterial({color});
    cube = new THREE.Mesh(geometry, material);
    renderer.setSize(window.innerWidth,  window.innerHeight);
    cubeRef.current.innerHTML = '';
    cubeRef.current.appendChild(renderer.domElement);
    scene.add(cube);
    camera.position.z = 5;
    animate();
  }, [color])

Also you might need to save the previous positioning or rotation somewhere.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文