/** * Sonofinity Custom Animations for Divi * Add to Divi Theme Options → Integration → Add code to */ document.addEventListener('DOMContentLoaded', function() { // Initialize Lucide Icons if (typeof lucide !== 'undefined') { lucide.createIcons(); } // Scroll Animations function initScrollAnimations() { 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-in'); // If element has data-count attribute, animate counting if (entry.target.hasAttribute('data-count')) { animateCounter(entry.target); } // Stop observing after animation triggers observer.unobserve(entry.target); } }); }, observerOptions); // Observe all elements with animation classes document.querySelectorAll('.animate-on-scroll').forEach(el => { observer.observe(el); }); } // Animate number counters function animateCounter(element) { const target = parseInt(element.getAttribute('data-count')); const duration = 2000; // 2 seconds const start = 0; const startTime = performance.now(); function updateCounter(currentTime) { const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); // Easing function for smooth animation const easeOutQuart = 1 - Math.pow(1 - progress, 4); const currentValue = Math.floor(start + (target - start) * easeOutQuart); element.textContent = currentValue.toLocaleString(); if (progress { card.addEventListener('mousemove', (e) => { const rect = card.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const centerX = rect.width / 2; const centerY = rect.height / 2; const rotateY = ((x - centerX) / centerX) * 5; // Max 5 degrees rotation const rotateX = ((centerY - y) / centerY) * 5; card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.02, 1.02, 1.02)`; }); card.addEventListener('mouseleave', () => { card.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)'; card.style.transition = 'transform 0.5s cubic-bezier(0.23, 1, 0.32, 1)'; }); }); } // Frequency visualization function initFrequencyVisualization() { const frequencySliders = document.querySelectorAll('.frequency-slider'); frequencySliders.forEach(slider => { const visualization = slider.nextElementSibling; slider.addEventListener('input', function() { const frequency = this.value; const amplitude = calculateAmplitude(frequency); // Update visualization if (visualization && visualization.classList.contains('frequency-wave')) { updateWaveform(visualization, frequency, amplitude); } // Update frequency display const display = slider.parentElement.querySelector('.frequency-display'); if (display) { display.textContent = `${frequency} Hz`; } }); }); } function calculateAmplitude(frequency) { // Simulate frequency response curve if (frequency { const scrollY = window.scrollY; parallaxSections.forEach(section => { const speed = section.getAttribute('data-parallax-speed') || 0.5; const yPos = -(scrollY * speed); section.style.transform = `translate3d(0, ${yPos}px, 0)`; }); }); } // Initialize everything function init() { initScrollAnimations(); init3DHover(); initFrequencyVisualization(); initParallax(); // Add animation class to body to trigger CSS animations document.body.classList.add('loaded'); } // Start initialization init(); // Reinitialize on Divi module load (for builder compatibility) if (typeof et_pb_smooth_scroll !== 'undefined') { window.et_pb_smooth_scroll = function($, speed, easing) { // Custom smooth scroll implementation $('html, body').animate({ scrollTop: 0 }, speed, easing); }; } }); // Custom cursor for technical areas document.addEventListener('DOMContentLoaded', function() { const technicalAreas = document.querySelectorAll('.technical-area, .engineering-diagram'); technicalAreas.forEach(area => { area.addEventListener('mouseenter', () => { document.body.style.cursor = 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'32\' height=\'32\' viewBox=\'0 0 32 32\'%3E%3Cpath d=\'M16 4L28 16L16 28L4 16Z\' fill=\'none\' stroke=\'%2300B7A8\' stroke-width=\'2\'/%3E%3Cline x1=\'16\' y1=\'4\' x2=\'16\' y2=\'28\' stroke=\'%2300B7A8\' stroke-width=\'2\'/%3E%3Cline x1=\'4\' y1=\'16\' x2=\'28\' y2=\'16\' stroke=\'%2300B7A8\' stroke-width=\'2\'/%3E%3C/svg%3E") 16 16, crosshair'; }); area.addEventListener('mouseleave', () => { document.body.style.cursor = 'default'; }); }); });

Sales & Consultation

Questions & Comments

Copyright © 2026 SONOFINITY All Rights Reserved.