From 46c9ed9a2da48dd1e0b9316f0e373061883895f4 Mon Sep 17 00:00:00 2001 From: anshk Date: Wed, 1 Apr 2026 20:12:04 +0530 Subject: [PATCH] feat: add scene for task2 n vanilla --- Week-2/Task-2/vanilla/index.html | 73 ++++++++++++++++- Week-2/Task-2/vanilla/main.js | 130 +++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 2 deletions(-) diff --git a/Week-2/Task-2/vanilla/index.html b/Week-2/Task-2/vanilla/index.html index f168821..ac81e38 100644 --- a/Week-2/Task-2/vanilla/index.html +++ b/Week-2/Task-2/vanilla/index.html @@ -8,10 +8,11 @@ html, body { margin: 0; - background: white; + background: #f3f5f8; width: 100%; height: 100%; overflow: hidden; + font-family: "Avenir Next", "Segoe UI", sans-serif; } canvas { @@ -19,10 +20,78 @@ width: 100%; height: 100%; } + + #state-panel { + position: fixed; + top: 16px; + left: 16px; + z-index: 10; + background: rgba(255, 255, 255, 0.82); + border: 1px solid rgba(0, 0, 0, 0.12); + border-radius: 12px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); + padding: 12px; + display: flex; + flex-direction: column; + gap: 8px; + backdrop-filter: blur(6px); + } + + #state-panel h2 { + margin: 0; + font-size: 14px; + letter-spacing: 0.03em; + color: #1b2530; + font-weight: 700; + } + + .state-buttons { + display: flex; + gap: 8px; + flex-wrap: wrap; + } + + .state-btn { + border: 1px solid #cfd8e3; + background: #ffffff; + color: #203448; + border-radius: 8px; + padding: 8px 10px; + font-size: 13px; + cursor: pointer; + transition: all 0.2s ease; + } + + .state-btn:hover { + border-color: #8ea2b8; + transform: translateY(-1px); + } + + .state-btn.active { + background: #203448; + border-color: #203448; + color: #f4f8fb; + } + + #hint { + margin: 0; + font-size: 12px; + color: #4f647a; + } - + +
+

Scene States

+
+ + + +
+

Press 1, 2, or 3 to switch state.

+
+ \ No newline at end of file diff --git a/Week-2/Task-2/vanilla/main.js b/Week-2/Task-2/vanilla/main.js index e69de29..5634170 100644 --- a/Week-2/Task-2/vanilla/main.js +++ b/Week-2/Task-2/vanilla/main.js @@ -0,0 +1,130 @@ +import * as THREE from 'three' + +const scene = new THREE.Scene() +scene.background = new THREE.Color(0xf3f5f8) + +const camera = new THREE.PerspectiveCamera( + 55, + window.innerWidth / window.innerHeight, + 0.1, + 100 +) +camera.position.set(0, 2, 7) +camera.lookAt(0, 0, 0) + +const renderer = new THREE.WebGLRenderer({ antialias: true }) +renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) +renderer.setSize(window.innerWidth, window.innerHeight) +document.body.appendChild(renderer.domElement) + +scene.add(new THREE.AmbientLight(0xffffff, 0.9)) + +const keyLight = new THREE.DirectionalLight(0xffffff, 1) +keyLight.position.set(3, 4, 5) +scene.add(keyLight) + +const objects = { + center: new THREE.Mesh( + new THREE.BoxGeometry(1.2, 1.2, 1.2), + new THREE.MeshStandardMaterial({ color: 0x2a9d8f }) + ), + left: new THREE.Mesh( + new THREE.BoxGeometry(0.9, 0.9, 0.9), + new THREE.MeshStandardMaterial({ color: 0xe76f51 }) + ), + right: new THREE.Mesh( + new THREE.BoxGeometry(0.9, 0.9, 0.9), + new THREE.MeshStandardMaterial({ color: 0x457b9d }) + ), +} + +scene.add(objects.center, objects.left, objects.right) + +const states = { + state1: { + center: { position: [0, 0, 0], rotation: [0, 0, 0], visible: true }, + left: { position: [0, 0, 0], rotation: [0, 0, 0], visible: false }, + right: { position: [0, 0, 0], rotation: [0, 0, 0], visible: false }, + }, + state2: { + center: { position: [0, 0, 0], rotation: [0.25, 0.4, 0], visible: true }, + left: { position: [-2.1, 0, 0.2], rotation: [0, 0.2, 0], visible: true }, + right: { position: [2.1, 0, -0.2], rotation: [0, -0.2, 0], visible: true }, + }, + state3: { + center: { position: [0, 1.3, 0], rotation: [0.6, 0.9, 0], visible: true }, + left: { position: [-1.2, -1, 1.2], rotation: [0.3, 0.3, 0.1], visible: true }, + right: { position: [0, 0, 0], rotation: [0, 0, 0], visible: false }, + }, +} + +const targets = { + center: { position: new THREE.Vector3(), rotation: new THREE.Euler() }, + left: { position: new THREE.Vector3(), rotation: new THREE.Euler() }, + right: { position: new THREE.Vector3(), rotation: new THREE.Euler() }, +} + +const buttons = Array.from(document.querySelectorAll('.state-btn')) +let activeState = 'state1' + +function updateButtonState(stateName) { + buttons.forEach((button) => { + button.classList.toggle('active', button.dataset.state === stateName) + }) +} + +function applyState(stateName) { + const nextState = states[stateName] + if (!nextState) { + return + } + + activeState = stateName + + Object.keys(objects).forEach((name) => { + const object = objects[name] + const config = nextState[name] + + targets[name].position.set(...config.position) + targets[name].rotation.set(...config.rotation) + object.visible = config.visible + }) + + updateButtonState(stateName) +} + +buttons.forEach((button) => { + button.addEventListener('click', () => { + applyState(button.dataset.state) + }) +}) + +window.addEventListener('keydown', (event) => { + if (event.key === '1') applyState('state1') + if (event.key === '2') applyState('state2') + if (event.key === '3') applyState('state3') +}) + +applyState(activeState) + +function animate() { + Object.keys(objects).forEach((name) => { + const object = objects[name] + const target = targets[name] + + object.position.lerp(target.position, 0.1) + object.rotation.x += (target.rotation.x - object.rotation.x) * 0.1 + object.rotation.y += (target.rotation.y - object.rotation.y) * 0.1 + object.rotation.z += (target.rotation.z - object.rotation.z) * 0.1 + }) + + renderer.render(scene, camera) +} + +renderer.setAnimationLoop(animate) + +window.addEventListener('resize', () => { + camera.aspect = window.innerWidth / window.innerHeight + camera.updateProjectionMatrix() + renderer.setSize(window.innerWidth, window.innerHeight) +})