Overview
The scene supports three interaction modes: clicking on furniture to zoom in, pressing Escape to return to the default view, and automatic camera repositioning when the viewport is resized or the device orientation changes.Click to zoom
Every major mesh in the bedroom scene (desk, monitor, PC, keyboard, chair) is wrapped in a group with anonClick handler. Clicking any of these triggers handleMeshClick:
src/models/Computer.jsx
handleMeshClick:
src/models/Computer.jsx
Aspect ratio to camera position mapping
| Condition | Aspect ratio | Camera position | Layout |
|---|---|---|---|
aspectRatio > 1.62 | e.g. 16:9 ultrawide | [-0.84, -0.272, 1.42] | Widescreen |
aspectRatio > 0.6666 | e.g. 4:3, 16:9 | [-0.83, -0.1, 1] | Standard |
| else | portrait / narrow | [-0.85, 0, 0.5] | Portrait |
[0.13, -Math.PI/2, 0] — slightly tilted down and facing left to center the monitor in the frame.
GSAP camera animation
Camera position and rotation changes are animated with GSAP rather than applied instantly. TwouseEffect hooks watch for changes to targetPosition and targetRotation and drive the animation:
src/models/Computer.jsx
controlsRef points to the <group> inside PresentationControls, so animating its position and rotation moves the entire scene relative to the fixed camera.
Escape key to reset
PressingEscape at any time returns the scene to its default state:
src/models/Computer.jsx
[0, -Math.PI/2 + 0.5, 0] (approximately −1.07 radians on the Y axis), which angles the bedroom slightly to present the monitor toward the viewer. The GSAP animations described above handle the smooth transition back.
Orientation change and resize handling
If the user is currently in a zoomed-in view and resizes the browser or rotates their device, the camera position is recalculated to match the new aspect ratio:src/models/Computer.jsx
isRotatable changes. When isRotatable is true (default view), the listeners are not attached — there is no camera to reposition. When the user clicks into the zoomed view (isRotatable becomes false), the listeners attach and will fire on any subsequent resize or orientation change.
orientationchange is a mobile-specific event that fires when the device is rotated. Listening to both resize and orientationchange ensures the camera repositions correctly on both desktop (window resize) and mobile (rotation).PresentationControls snap behavior
While in the default (non-zoomed) view,PresentationControls is enabled and allows the user to drag and rotate the scene. The snap prop is set to true:
src/models/Computer.jsx
snap={true}, releasing the drag causes the scene to spring back to the rotation value provided via the rotation prop. In the default view this is [0, 0, 0], so the model always returns to its forward-facing orientation after the user lets go. This ensures the monitor remains visible and the scene does not drift into an awkward angle between interactions.