// 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...

`; const response = await fetch(mockApiUrl); const posts = await response.json(); container.innerHTML = ''; posts.forEach((post, index) => { const colors = ['primary', 'secondary']; const color = colors[index % colors.length]; const card = document.createElement('div'); card.className = 'blog-card bg-white dark:bg-gray-800 rounded-2xl shadow-xl overflow-hidden transform transition-all duration-300 hover:shadow-2xl'; card.innerHTML = `
${post.title}
${color === 'primary' ? 'TECHNOLOGY' : 'DESIGN'} ${Math.floor(Math.random() * 30) + 1} min read

${post.title}

${post.body}

${post.userId}
Author ${post.userId}
Read More
`; container.appendChild(card); }); feather.replace(); } catch (error) { console.error('Error loading blog posts:', error); container.innerHTML = `

Unable to load articles. Please check your connection.

`; feather.replace(); } } // Theme Toggle Functionality function initThemeToggle() { const themeToggles = document.querySelectorAll('[data-theme-toggle]'); if (!themeToggles.length) return; const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)'); const currentTheme = localStorage.getItem('theme') || (prefersDarkScheme.matches ? 'dark' : 'light'); if (currentTheme === 'dark') { document.documentElement.classList.add('dark'); } themeToggles.forEach(themeToggle => { themeToggle.addEventListener('click', () => { const isDark = document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', isDark ? 'dark' : 'light'); // Update icons const icons = document.querySelectorAll('[data-feather]'); icons.forEach(icon => { if (icon.getAttribute('data-feather') === 'moon' || icon.getAttribute('data-feather') === 'sun') { icon.setAttribute('data-feather', isDark ? 'sun' : 'moon'); } }); feather.replace(); }); }); // Also update icons on initial load setTimeout(() => { const isDark = document.documentElement.classList.contains('dark'); const icons = document.querySelectorAll('[data-feather]'); icons.forEach(icon => { if (icon.getAttribute('data-feather') === 'moon' || icon.getAttribute('data-feather') === 'sun') { icon.setAttribute('data-feather', isDark ? 'sun' : 'moon'); } }); feather.replace(); }, 100); } // Smooth Scroll Implementation function initSmoothScroll() { document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function(e) { e.preventDefault(); const targetId = this.getAttribute('href'); if (targetId === '#') return; const targetElement = document.querySelector(targetId); if (targetElement) { window.scrollTo({ top: targetElement.offsetTop - 80, behavior: 'smooth' }); } }); }); } // CMS Dashboard Demo function initCMSDashboard() { // Simulate real-time updates setInterval(() => { const stats = document.querySelectorAll('.stat-value'); stats.forEach(stat => { if (stat.classList.contains('animate-pulse')) { stat.classList.remove('animate-pulse'); setTimeout(() => stat.classList.add('animate-pulse'), 10); } }); }, 3000); // Simulate API call for CMS status setTimeout(() => { const statusIndicator = document.getElementById('cms-status'); if (statusIndicator) { statusIndicator.innerHTML = `
CMS Connected • Real-time Sync Active
`; } }, 1500); }