| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Infinite Vortex</title> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> |
| <style> |
| body { |
| margin: 0; |
| overflow: hidden; |
| background: #000; |
| } |
| canvas { |
| display: block; |
| } |
| </style> |
| </head> |
| <body> |
| <script> |
| const scene = new THREE.Scene(); |
| const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); |
| const renderer = new THREE.WebGLRenderer({ antialias: true }); |
| |
| renderer.setSize(window.innerWidth, window.innerHeight); |
| document.body.appendChild(renderer.domElement); |
| |
| const geometry = new THREE.TorusKnotGeometry(10, 3, 100, 16); |
| const material = new THREE.MeshBasicMaterial({ |
| color: 0xffffff, |
| wireframe: true |
| }); |
| const vortex = new THREE.Mesh(geometry, material); |
| scene.add(vortex); |
| |
| camera.position.z = 30; |
| |
| function animate() { |
| requestAnimationFrame(animate); |
| vortex.rotation.x += 0.01; |
| vortex.rotation.y += 0.01; |
| vortex.scale.x *= 1.001; |
| vortex.scale.y *= 1.001; |
| vortex.scale.z *= 1.001; |
| |
| |
| if(vortex.scale.x > 5) { |
| vortex.scale.set(1, 1, 1); |
| } |
| |
| renderer.render(scene, camera); |
| } |
| |
| window.addEventListener('resize', () => { |
| camera.aspect = window.innerWidth / window.innerHeight; |
| camera.updateProjectionMatrix(); |
| renderer.setSize(window.innerWidth, window.innerHeight); |
| }); |
| |
| animate(); |
| </script> |
| </body> |
| </html> |