57 lines
1.7 KiB
JavaScript
57 lines
1.7 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
|
|
});
|