'How to dynamically change a mesh color with React and Three.js
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 auseEffectwith `color as dep.
Thanks
Solution 1:[1]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dharman |
