| |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { |
| anchor.addEventListener('click', function (e) { |
| e.preventDefault(); |
| document.querySelector(this.getAttribute('href')).scrollIntoView({ |
| behavior: 'smooth' |
| }); |
| }); |
| }); |
|
|
| |
| function toggleMobileMenu() { |
| const menu = document.getElementById('mobile-menu'); |
| menu.classList.toggle('hidden'); |
| menu.classList.toggle('flex'); |
| } |
|
|
| |
| function animateCounters() { |
| const counters = document.querySelectorAll('.counter'); |
| const speed = 200; |
| |
| counters.forEach(counter => { |
| const target = +counter.getAttribute('data-target'); |
| const count = +counter.innerText; |
| const increment = target / speed; |
| |
| if (count < target) { |
| counter.innerText = Math.ceil(count + increment); |
| setTimeout(animateCounters, 1); |
| } else { |
| counter.innerText = target.toLocaleString(); |
| } |
| }); |
| } |
|
|
| |
| const observerOptions = { |
| threshold: 0.1, |
| rootMargin: '0px 0px -100px 0px' |
| }; |
|
|
| const observer = new IntersectionObserver((entries) => { |
| entries.forEach(entry => { |
| if (entry.isIntersecting) { |
| entry.target.classList.add('animate-fadeIn'); |
| observer.unobserve(entry.target); |
| } |
| }); |
| }, observerOptions); |
|
|
| document.querySelectorAll('[data-animate]').forEach(el => { |
| observer.observe(el); |
| }); |
|
|
| |
| document.addEventListener('DOMContentLoaded', () => { |
| |
| if (document.querySelector('.counter')) { |
| animateCounters(); |
| } |
| }); |