56 lines
No EOL
1.8 KiB
JavaScript
56 lines
No EOL
1.8 KiB
JavaScript
// Counter animation for stats
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
const counters = document.querySelectorAll('.stat-number');
|
|
let hasCounted = false;
|
|
|
|
function animateCounters() {
|
|
if (hasCounted) return;
|
|
|
|
counters.forEach(counter => {
|
|
const target = parseInt(counter.getAttribute('data-count'));
|
|
const duration = 2000; // 2 seconds
|
|
const frameDuration = 1000 / 60; // 60 frames per second
|
|
const totalFrames = Math.round(duration / frameDuration);
|
|
let frame = 0;
|
|
|
|
const counterInterval = setInterval(() => {
|
|
frame++;
|
|
const progress = frame / totalFrames;
|
|
const currentCount = Math.round(target * progress);
|
|
|
|
counter.textContent = currentCount;
|
|
|
|
if (frame === totalFrames) {
|
|
clearInterval(counterInterval);
|
|
}
|
|
}, frameDuration);
|
|
|
|
counter.classList.add('animated');
|
|
});
|
|
|
|
hasCounted = true;
|
|
}
|
|
|
|
// Check if element is in viewport
|
|
function isInViewport(element) {
|
|
const rect = element.getBoundingClientRect();
|
|
return (
|
|
rect.top >= 0 &&
|
|
rect.left >= 0 &&
|
|
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
|
|
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
|
);
|
|
}
|
|
|
|
// Check on scroll and on load
|
|
function checkCounters() {
|
|
const statsContainer = document.querySelector('.stats-container');
|
|
if (statsContainer && isInViewport(statsContainer)) {
|
|
animateCounters();
|
|
window.removeEventListener('scroll', checkCounters);
|
|
}
|
|
}
|
|
|
|
window.addEventListener('scroll', checkCounters);
|
|
checkCounters(); // Check on page load
|
|
}); |