// Three.js Jellyfish Animation class JellyfishScene { constructor() { this.scene = new THREE.Scene(); this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); this.renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); this.jellyfishes = []; this.init(); } init() { // Setup renderer this.renderer.setSize(window.innerWidth, window.innerHeight); this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); document.getElementById('jellyfish-canvas').appendChild(this.renderer.domElement); // Camera position this.camera.position.z = 15; // Add ambient light const ambientLight = new THREE.AmbientLight(0x222222); this.scene.add(ambientLight); // Add directional lights for glow effect const cyanLight = new THREE.PointLight(0x06b6d4, 2, 50); cyanLight.position.set(10, 10, 10); this.scene.add(cyanLight); const purpleLight = new THREE.PointLight(0x9333ea, 2, 50); purpleLight.position.set(-10, -10, 10); this.scene.add(purpleLight); // Create jellyfishes this.createJellyfishes(8); // Handle window resize window.addEventListener('resize', () => this.onWindowResize()); // Start animation this.animate(); } createJellyfishes(count) { for (let i = 0; i < count; i++) { const jellyfish = this.createJellyfish(); jellyfish.position.x = (Math.random() - 0.5) * 30; jellyfish.position.y = (Math.random() - 0.5) * 20; jellyfish.position.z = (Math.random() - 0.5) * 20; this.jellyfishes.push(jellyfish); this.scene.add(jellyfish); } } createJellyfish() { const group = new THREE.Group(); // Bell (main body) const bellGeometry = new THREE.SphereGeometry(0.8, 32, 16, 0, Math.PI * 2, 0, Math.PI / 2); const bellMaterial = new THREE.MeshPhongMaterial({ color: 0x06b6d4, transparent: true, opacity: 0.3, shininess: 100 }); const bell = new THREE.Mesh(bellGeometry, bellMaterial); group.add(bell); // Tentacles const tentacleCount = 8; for (let i = 0; i < tentacleCount; i++) { const angle = (i / tentacleCount) * Math.PI * 2; const tentacle = this.createTentacle(); tentacle.position.y = -0.8; tentacle.rotation.x = Math.PI / 4; tentacle.rotation.z = angle; group.add(tentacle); } // Glow effect const glowGeometry = new THREE.SphereGeometry(1.2, 32, 16, 0, Math.PI * 2, 0, Math.PI / 2); const glowMaterial = new THREE.MeshBasicMaterial({ color: 0x9333ea, transparent: true, opacity: 0.1 }); const glow = new THREE.Mesh(glowGeometry, glowMaterial); group.add(glow); return group; } createTentacle() { const points = []; for (let i = 0; i <= 10; i++) { points.push(new THREE.Vector3(0, -i * 0.3, 0)); } const curve = new THREE.CatmullRomCurve3(points); const geometry = new THREE.TubeGeometry(curve, 20, 0.02, 8, false); const material = new THREE.MeshPhongMaterial({ color: 0x06b6d4, transparent: true, opacity: 0.6 }); return new THREE.Mesh(geometry, material); } onWindowResize() { this.camera.aspect = window.innerWidth / window.innerHeight; this.camera.updateProjectionMatrix(); this.renderer.setSize(window.innerWidth, window.innerHeight); } animate() { requestAnimationFrame(() => this.animate()); // Animate jellyfishes this.jellyfishes.forEach((jellyfish, index) => { const time = Date.now() * 0.001; const floatSpeed = 0.5 + index * 0.1; // Floating motion jellyfish.position.y += Math.sin(time + index) * 0.005; jellyfish.position.x += Math.cos(time + index * 0.5) * 0.003; // Gentle rotation jellyfish.rotation.y += 0.001; jellyfish.rotation.x += Math.sin(time + index) * 0.0005; // Tentacle movement jellyfish.children.forEach((child, childIndex) => { if (childIndex > 0) { // Skip the bell child.rotation.x = Math.PI / 4 + Math.sin(time + childIndex) * 0.1; }); }); this.renderer.render(this.scene, this.camera); } } // Initialize when DOM is loaded document.addEventListener('DOMContentLoaded', () => { // Initialize Three.js scene new JellyfishScene(); // Add scroll animations const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate-fade-in'); } }, observerOptions); // Observe all glass cards document.querySelectorAll('.glass-card').forEach(card => { observer.observe(card); }); }); // Smooth scrolling for anchor links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); });