| 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() { |
| |
| this.renderer.setSize(window.innerWidth, window.innerHeight); |
| this.renderer.setClearColor(0x000000, 0); |
| document.getElementById('container').appendChild(this.renderer.domElement); |
|
|
| |
| 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); |
| |
| |
| 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); |
| } |
|
|
| |
| 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); |
|
|
| |
| this.camera.position.z = 15; |
|
|
| |
| document.addEventListener('mousemove', (event) => { |
| this.mouseX = (event.clientX / window.innerWidth) * 2 - 1; |
| this.mouseY = -(event.clientY / window.innerHeight) * 2 + 1; |
| }); |
|
|
| |
| window.addEventListener('resize', () => { |
| this.camera.aspect = window.innerWidth / window.innerHeight; |
| this.camera.updateProjectionMatrix(); |
| this.renderer.setSize(window.innerWidth, window.innerHeight); |
| }); |
| } |
|
|
| animate() { |
| requestAnimationFrame(() => this.animate()); |
|
|
| |
| this.targetX += (this.mouseX - this.targetX) * 0.05; |
| this.targetY += (this.mouseY - this.targetY) * 0.05; |
|
|
| |
| this.cubes.forEach((cube, index) => { |
| const data = cube.userData; |
| |
| |
| const distanceToCenter = cube.position.length(); |
| const mouseDistance = Math.sqrt(this.targetX * this.targetX + this.targetY * this.targetY); |
| |
| |
| data.warpFactor = Math.min(1, mouseDistance * 2 + (1 - distanceToCenter / 20)); |
| |
| |
| 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); |
| |
| |
| 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; |
| |
| |
| const scale = 1 + data.warpFactor * 0.5; |
| cube.scale.set(scale, scale, scale); |
| |
| |
| cube.material.color.setHSL( |
| (index * 0.1 + time * 0.1) % 1, |
| 0.8, |
| 0.6 + data.warpFactor * 0.4 |
| ); |
| |
| |
| cube.material.opacity = 0.6 + Math.sin(time * 2 + index) * 0.2; |
| }); |
|
|
| this.renderer.render(this.scene, this.camera); |
| } |
| } |
|
|
| |
| window.addEventListener('load', () => { |
| new CubeWarp(); |
| }); |