feat: implement multi-object selection behavior audit for week 3 task 4 in vanilla

This commit is contained in:
divyap 2026-04-12 12:53:53 +05:30
parent d99a41b6b8
commit d3989465e4
3 changed files with 105 additions and 39 deletions

View File

@ -2,13 +2,21 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Task 4 — Click To Highlight / Select</title>
<style>
body { margin: 0; padding: 0; overflow: hidden; background: white; font-family: sans-serif; }
</style>
<title>Task 4 — Selection Behavior Audit</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<h1>Interaction Pattern- click on the object</h1>
<div id="instructions">
<h2>Task 4 Audit</h2>
<p>Click objects to select/deselect them.</p>
<ul>
<li>Scale shifts</li>
<li>Glow / Emissive toggle</li>
<li>Automatic deselection on background click</li>
</ul>
</div>
<script type="module" src="./main.js"></script>
</body>
</html>

View File

@ -5,66 +5,81 @@ const scene = new THREE.Scene();
scene.background = new THREE.Color("white");
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
camera.position.set(0, 3, 10);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const geometry = new THREE.TorusKnotGeometry(1, 0.4, 100, 16);
const material = new THREE.MeshStandardMaterial({ color: "#ccc", roughness: 0.5 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
scene.add(new THREE.AmbientLight(0xffffff, 0.6));
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(5, 5, 5);
scene.add(pointLight);
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 10, 5);
scene.add(light);
const objects = [];
const geometries = [
new THREE.BoxGeometry(2, 2, 2),
new THREE.SphereGeometry(1.2, 32, 32),
new THREE.TorusGeometry(1.2, 0.4, 16, 100)
];
const positions = [-5, 0, 5];
const colors = ["#ff4f4f", "#4f8cff", "#4fff8c"];
geometries.forEach((geo, i) => {
const mat = new THREE.MeshStandardMaterial({
color: colors[i],
roughness: 0.4,
metalness: 0.3,
emissive: new THREE.Color(0x000000)
});
const mesh = new THREE.Mesh(geo, mat);
mesh.position.set(positions[i], 0, 0);
scene.add(mesh);
objects.push(mesh);
});
let selectedObject = null;
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
let isSelected = false;
window.addEventListener("click", (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObject(mesh);
const intersects = raycaster.intersectObjects(objects);
if (selectedObject) {
selectedObject.scale.set(1, 1, 1);
selectedObject.material.emissive.setHex(0x000000);
}
if (intersects.length > 0) {
isSelected = !isSelected;
updateAppearance();
const clicked = intersects[0].object;
if (selectedObject === clicked) {
selectedObject = null;
} else {
selectedObject = clicked;
selectedObject.scale.set(1.25, 1.25, 1.25);
selectedObject.material.emissive.setHex(0x333333);
}
} else {
selectedObject = null;
}
});
function updateAppearance() {
if (isSelected) {
mesh.scale.set(1.2, 1.2, 1.2);
mesh.material.color.set("#3498db");
mesh.material.emissive.set("#1e3799");
mesh.material.emissiveIntensity = 0.5;
} else {
mesh.scale.set(1, 1, 1);
mesh.material.color.set("#ccc");
mesh.material.emissive.set("#000");
mesh.material.emissiveIntensity = 0;
}
}
function animate() {
requestAnimationFrame(animate);
controls.update();
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});

View File

@ -0,0 +1,43 @@
body {
margin: 0;
overflow: hidden;
font-family: 'Inter', system-ui, -apple-system, sans-serif;
}
#instructions {
position: absolute;
top: 20px;
left: 20px;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(12px);
padding: 24px;
border-radius: 16px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
border: 1px solid rgba(255, 255, 255, 0.3);
max-width: 300px;
z-index: 100;
}
h2 {
margin: 0 0 12px 0;
font-size: 1.25rem;
color: #1a1a1a;
}
p {
margin: 0 0 12px 0;
font-size: 0.95rem;
color: #4a4a4a;
line-height: 1.5;
}
ul {
margin: 0;
padding-left: 20px;
color: #666;
font-size: 0.85rem;
}
li {
margin-bottom: 6px;
}