Meroar's picture
Create a simple homepage that displays rotating and translating cubes that warp into eachother based on mouse movement
1a62613 verified
Raw
History Blame Contribute Delete
5.61 kB
class CubeWarp {
constructor() {
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
this.cubes = [];
this.mouseX = 0;
this.mouseY = 0;
this.targetX = 0;
this.targetY = 0;
this.init();
this.animate();
}
init() {
// Setup renderer
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.setClearColor(0x000000, 0);
document.getElementById('container').appendChild(this.renderer.domElement);
// Create multiple cubes with different colors and positions
const colors = [
0xff6b6b, 0x4ecdc4, 0x45b7d1, 0x96ceb4, 0xffeaa7,
0xdda0dd, 0x98d8c8, 0xf7dc6f, 0xbb8fce
];
for (let i = 0; i < 15; i++) {
const geometry = new THREE.BoxGeometry(2, 2, 2);
const material = new THREE.MeshPhongMaterial({
color: colors[i % colors.length],
transparent: true,
opacity: 0.8,
shininess: 100
});
const cube = new THREE.Mesh(geometry, material);
// Position cubes in a spherical arrangement
const radius = 8 + Math.random() * 4;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos((Math.random() * 2) - 1);
cube.position.x = radius * Math.sin(phi) * Math.cos(theta);
cube.position.y = radius * Math.sin(phi) * Math.sin(theta);
cube.position.z = radius * Math.cos(phi);
cube.userData = {
originalPosition: cube.position.clone(),
speed: 0.5 + Math.random() * 1.5,
rotationSpeed: {
x: (Math.random() - 0.5) * 0.02,
y: (Math.random() - 0.5) * 0.02,
z: (Math.random() - 0.5) * 0.02
},
warpFactor: 0
};
this.scene.add(cube);
this.cubes.push(cube);
}
// Add lights
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
this.scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 5, 5);
this.scene.add(directionalLight);
const pointLight = new THREE.PointLight(0x4ecdc4, 1, 100);
pointLight.position.set(-5, -5, -5);
this.scene.add(pointLight);
// Position camera
this.camera.position.z = 15;
// Mouse move event
document.addEventListener('mousemove', (event) => {
this.mouseX = (event.clientX / window.innerWidth) * 2 - 1;
this.mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
});
// Window resize
window.addEventListener('resize', () => {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
});
}
animate() {
requestAnimationFrame(() => this.animate());
// Smooth mouse movement
this.targetX += (this.mouseX - this.targetX) * 0.05;
this.targetY += (this.mouseY - this.targetY) * 0.05;
// Update cubes
this.cubes.forEach((cube, index) => {
const data = cube.userData;
// Calculate warp effect based on mouse position and cube distance
const distanceToCenter = cube.position.length();
const mouseDistance = Math.sqrt(this.targetX * this.targetX + this.targetY * this.targetY);
// Warp factor increases with mouse movement and proximity
data.warpFactor = Math.min(1, mouseDistance * 2 + (1 - distanceToCenter / 20));
// Rotation
cube.rotation.x += data.rotationSpeed.x * (1 + data.warpFactor * 2);
cube.rotation.y += data.rotationSpeed.y * (1 + data.warpFactor * 2);
cube.rotation.z += data.rotationSpeed.z * (1 + data.warpFactor * 2);
// Position warping - cubes move towards each other and distort
const time = Date.now() * 0.001;
const warpX = Math.sin(time + index) * data.warpFactor * 3;
const warpY = Math.cos(time + index * 0.7) * data.warpFactor * 3;
const warpZ = Math.sin(time * 0.5 + index * 0.3) * data.warpFactor * 3;
cube.position.x = data.originalPosition.x + warpX + this.targetX * 2;
cube.position.y = data.originalPosition.y + warpY + this.targetY * 2;
cube.position.z = data.originalPosition.z + warpZ;
// Scale warping
const scale = 1 + data.warpFactor * 0.5;
cube.scale.set(scale, scale, scale);
// Color intensity based on warp factor
cube.material.color.setHSL(
(index * 0.1 + time * 0.1) % 1,
0.8,
0.6 + data.warpFactor * 0.4
);
// Opacity pulsing
cube.material.opacity = 0.6 + Math.sin(time * 2 + index) * 0.2;
});
this.renderer.render(this.scene, this.camera);
}
}
// Initialize when page loads
window.addEventListener('load', () => {
new CubeWarp();
});