Issue Description
I'm using react-three-fiber and I have a function called HoverableCube that creates a transparent, interactive cube. When clicked, it moves le camera clos to it and should have the camera face the cube.
Parameters:
Parameters:
position, rotation, scale, moveTo, setLastCameraPosition, controlsRef
position, rotation, scale → Define where the cube is and its size. moveTo → The camera moves to this 3D vector when the cube is clicked. setLastCameraPosition → Stores the previous camera position before moving controlRef reference state for control.
Problem 📌 The camera does NOT face the cube after moving to moveTo. No matter where the cube is, the camera always faces (0,0,0) after the GSAP transition.
What I tried
- In my App() function:
const orbitRef = useRef()
Then, passed it down to HoverableCube:
<OrbitControls
makeDefault
ref={orbitRef}
enablePan={false}
enableZoom={true}
minPolarAngle={Math.PI / 2.2}
maxPolarAngle={Math.PI / 2.2}
/>
<HoverableCube
position={[0, -1, 0]}
moveTo={[5, 3, -5]}
setLastCameraPosition={setLastCameraPosition}
controlsRef={orbitRef} // Passed to cube
/>
- then Used controlsRef to set the
getPolarAngleandsetFromSpherical.
const handleClick = () => {
console.log('cube click. Moving to:', moveTo)
// for reset button
setLastCameraPosition([camera.position.x, camera.position.y, camera.position.z])
// camera transition to x,y,z
gsap.to(camera.position, {
x: moveTo[0],
y: moveTo[1],
z: moveTo[2],
duration: 1.5,
ease: 'power2.out',
})
// the code that controls camera look-at
const target = new THREE.Vector3(position[0], position[1], position[2]);
let sph = new THREE.Spherical(controlsRef.current.getDistance(),
controlsRef.current.getPolarAngle(), controlsRef.current.getAzimuthalAngle());
camera.position.setFromSpherical( sph ).add( target )
camera.lookAt( target )
// also tried this
camera.lookAt(position[0], position[1], position[2])
controls.target = controls.target || new Vector3();
controls.target.set(position[0], position[1], position[2]);
}
Expected Behavior: The camera moves to moveTo & camera faces the cube at position. Actual Behavior: The camera moves to moveTo. But it faces (0,0,0), NOT the cube
ive been tryuing to fix this for the past few days, im going crazy.
Edit:
For reference, this is my HoverableCube function:
function HoverableCube({ position, rotation, scale, moveTo, setLastCameraPosition, controlsRef }) {
const [hovered, setHovered] = useState(false)
const { camera, controls } = useThree()
const handleClick = () => {
console.log('cube click. Moving to:', moveTo)
// for reset button
setLastCameraPosition([camera.position.x, camera.position.y, camera.position.z])
// camera transition to x,y,z
gsap.to(camera.position, {
x: moveTo[0],
y: moveTo[1],
z: moveTo[2],
duration: 1.5,
ease: 'power2.out',
})
const target = new THREE.Vector3(position[0], position[1], position[2]);
let sph = new THREE.Spherical(controlsRef.current.getDistance(),
controlsRef.current.getPolarAngle(), controlsRef.current.getAzimuthalAngle());
camera.position.setFromSpherical( sph ).add( target )
camera.lookAt( target )
// Where i'm having issues with. Camera won't look at the position.
camera.lookAt(position[0], position[1], position[2])
controls.target = controls.target || new Vector3();
controls.target.set(position[0], position[1], position[2]);
}
return (
<group>
{/* Main Cube */}
<mesh
castShadow
receiveShadow
position={position}
rotation={rotation}
scale={scale}
onPointerOver={() => setHovered(true)}
onPointerOut={() => setHovered(false)}
onClick={handleClick} // camera click move
>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="blue" transparent={false} opacity={0.01} />
</mesh>
{/* White Outline on Hover */}
{hovered && (
<lineSegments position={position} rotation={rotation} scale={scale}>
<edgesGeometry attach="geometry" args={[new THREE.BoxGeometry(1, 1, 1)]} />
<lineBasicMaterial attach="material" color="white" linewidth={1} />
</lineSegments>
)}
</group>
)
}
sorry if its too crude just copy n pasting the function