// Main Application Script document.addEventListener('DOMContentLoaded', function() { // Initialize Three.js Scene initThreeJSScene(); initInteractive3DScene(); // Load Blog Posts from API loadBlogPosts(); // Theme Toggle Logic initThemeToggle(); // Smooth Scroll for Anchor Links initSmoothScroll(); // Initialize CMS Dashboard Demo initCMSDashboard(); }); // Three.js Background Animation function initThreeJSScene() { const container = document.getElementById('threejs-container'); if (!container) return; // Scene setup const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setSize(container.clientWidth, container.clientHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); container.appendChild(renderer.domElement); // Lighting const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); scene.add(ambientLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); directionalLight.position.set(5, 5, 5); scene.add(directionalLight); // Create floating geometric objects const geometryTypes = [ new THREE.TorusGeometry(1, 0.4, 16, 100), new THREE.IcosahedronGeometry(1, 0), new THREE.OctahedronGeometry(1, 0), new THREE.TorusKnotGeometry(1, 0.3, 100, 16) ]; const material = new THREE.MeshStandardMaterial({ color: 0x3b82f6, metalness: 0.3, roughness: 0.4, transparent: true, opacity: 0.8 }); const objects = []; for (let i = 0; i < 8; i++) { const geometry = geometryTypes[Math.floor(Math.random() * geometryTypes.length)]; const mesh = new THREE.Mesh(geometry, material.clone()); mesh.position.x = (Math.random() - 0.5) * 20; mesh.position.y = (Math.random() - 0.5) * 10; mesh.position.z = (Math.random() - 0.5) * 20; mesh.rotation.x = Math.random() * Math.PI; mesh.rotation.y = Math.random() * Math.PI; mesh.userData = { speed: 0.02 + Math.random() * 0.03, rotationSpeed: { x: (Math.random() - 0.5) * 0.02, y: (Math.random() - 0.5) * 0.02, z: (Math.random() - 0.5) * 0.02 }, floatAmplitude: 0.5 + Math.random() * 1, floatSpeed: 1 + Math.random() * 2, initialY: mesh.position.y }; mesh.material.color.setHSL(Math.random(), 0.7, 0.6); scene.add(mesh); objects.push(mesh); } camera.position.z = 15; // Animation loop function animate() { requestAnimationFrame(animate); objects.forEach(mesh => { // Floating animation mesh.position.y = mesh.userData.initialY + Math.sin(Date.now() * 0.001 * mesh.userData.floatSpeed) * mesh.userData.floatAmplitude; // Rotation mesh.rotation.x += mesh.userData.rotationSpeed.x; mesh.rotation.y += mesh.userData.rotationSpeed.y; mesh.rotation.z += mesh.userData.rotationSpeed.z; // Gentle orbit mesh.position.x += Math.cos(Date.now() * 0.001 * mesh.userData.speed) * 0.02; mesh.position.z += Math.sin(Date.now() * 0.001 * mesh.userData.speed) * 0.02; }); renderer.render(scene, camera); } // Handle window resize window.addEventListener('resize', () => { camera.aspect = container.clientWidth / container.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(container.clientWidth, container.clientHeight); }); animate(); } // Interactive 3D Scene function initInteractive3DScene() { const container = document.getElementById('interactive-3d'); if (!container) return; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setSize(container.clientWidth, container.clientHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); container.appendChild(renderer.domElement); // Add OrbitControls const controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; // Create a more complex 3D object const geometry = new THREE.IcosahedronGeometry(3, 2); const material = new THREE.MeshNormalMaterial({ wireframe: false }); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); // Add wireframe version const wireframe = new THREE.LineSegments( new THREE.WireframeGeometry(geometry), new THREE.LineBasicMaterial({ color: 0xffffff, linewidth: 2 }) ); mesh.add(wireframe); // Add particles around the object const particleGeometry = new THREE.BufferGeometry(); const particleCount = 1000; const positions = new Float32Array(particleCount * 3); for (let i = 0; i < particleCount * 3; i += 3) { const radius = 5 + Math.random() * 3; const theta = Math.random() * Math.PI * 2; const phi = Math.random() * Math.PI; positions[i] = radius * Math.sin(phi) * Math.cos(theta); positions[i + 1] = radius * Math.cos(phi); positions[i + 2] = radius * Math.sin(phi) * Math.sin(theta); } particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); const particleMaterial = new THREE.PointsMaterial({ color: 0xa855f7, size: 0.05, transparent: true }); const particles = new THREE.Points(particleGeometry, particleMaterial); scene.add(particles); camera.position.z = 10; // Animation loop function animate() { requestAnimationFrame(animate); mesh.rotation.x += 0.005; mesh.rotation.y += 0.005; particles.rotation.y += 0.001; controls.update(); renderer.render(scene, camera); } // Handle window resize window.addEventListener('resize', () => { camera.aspect = container.clientWidth / container.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(container.clientWidth, container.clientHeight); }); animate(); } // Load Blog Posts from Mock API async function loadBlogPosts() { const container = document.getElementById('blog-posts'); if (!container) return; // Mock API URL - In a real implementation, this would be your headless CMS endpoint const mockApiUrl = 'https://jsonplaceholder.typicode.com/posts?_limit=6'; try { container.innerHTML = `
Loading articles from CMS...
${post.body}
Unable to load articles. Please check your connection.