🟢 Live Demo: andrei-leonichev-three-js-demo.vercel.app
An interactive 3D demo built with React and Three.js: a vertical stack of “apartments” (cubes) that you can rotate, hover, and select.
When you click a cube, a popup appears showing its apartment number.
Built as a small technical assignment / demo. Focused on camera control, raycasting, hover/selection states, and touch support.
- Interactive 3D building made of cubes
- Mouse and touch support (rotate / select)
- Hover highlight and click selection
- React-based popup overlay
- Configurable 3D scene and camera settings
- React (Hooks, functional components)
- Three.js for 3D rendering
- CSS / SCSS for layout and popup styling
Requires Node 18+
# Install dependencies
npm install
# Run the project
npm startIf you’re using Vite:
npm run devThen open http://localhost:3000 in your browser.
src/
components/
PopUp.jsx
Skyscraper.jsx
settings/
common-settings.js
styles/
app.css
pop-up.css
App.jsx
main.jsx (or index.jsx)
Skyscraper.jsx— Three.js setup, camera, lighting, cube creation, hover and selection logicPopUp.jsx— Popup overlay displaying the selected apartment numberApp.jsx— Main entry point connecting components
Desktop:
- Drag → rotate the building
- Hover → highlight cube
- Click → show popup
Touch devices:
- Drag → rotate the building
- Tap → show popup
All main parameters are stored in settings/common-settings.js:
export default {
camera: {
fov: 75,
aspect: window.innerWidth / window.innerHeight,
near: 0.1,
far: 1000,
position: { x: 0, y: 3, z: 10 },
},
lighting: {
ambient: {
color: 0xf0f0f0, // Soft white light
},
directional: {
color: 0xf0f0f0,
intensity: 1,
position: { x: 5, y: 10, z: 7.5 },
},
},
building: {
block: {
geometry: { width: 2, height: 0.5, depth: 2 },
spacing: { x: 1.1, y: 0.6, z: 1.1 },
defaultColor: 0xf0f0f0 , // Default grey color
highlightColor: 0x00ff00, // Green color for highlighting
selectColor: 0x00ffff, // Green color for highlighting
},
height: 10, // Number of floors
},
scene: {
backgroundColor: 0xf0f0f0, // Light grey background color
},
cameraControls: {
radius: 10, // Distance from the camera to the center of the building
initialTheta: 45,
initialPhi: Math.PI / 3,
thetaSensitivity: 0.01,
phiSensitivity: 0.005,
phiClamp: { min: 0.8, max: Math.PI - 1.4 },
},
};- Uses raycasting to detect hovered and clicked cubes
- Camera rotates via spherical coordinates (
theta,phi) - State stored in both
useRef(persistent state) anduseState(popup visibility) - Responsive — resizes with window events
- Add floor navigation or labels
- Add shadows or materials for realism
- Improve accessibility (keyboard rotation)
- Use performance optimizations for mobile
MIT — free to use and modify.