Files
student-web-if-development-kit/groups/ApeNameTeamE/assets/js/counter.js
T
Araya's Project 8e9137f725 feat(ApeNameTeamE): tambah proyek web-beasiswa-untan
Memindahkan seluruh file web-beasiswa-untan (assets, data, index.html,
SRS/SDD, PROJECT_CONTEXT) ke dalam folder grup ApeNameTeamE.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 13:33:40 +07:00

54 lines
1.5 KiB
JavaScript

// =====================================================
// counter.js — Animasi Counter Statistik
// Menggunakan IntersectionObserver + requestAnimationFrame
// =====================================================
/**
* Animasi angka dari 0 ke nilai target
* @param {HTMLElement} el - Elemen yang menampilkan angka
* @param {number} target - Angka target
* @param {number} duration - Durasi animasi dalam ms
*/
function animateCounter(el, target, duration = 1800) {
const startTime = performance.now();
function update(currentTime) {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
// Ease out cubic — percepat di awal, lambat di akhir
const eased = 1 - Math.pow(1 - progress, 3);
const current = Math.round(eased * target);
el.textContent = current;
if (progress < 1) {
requestAnimationFrame(update);
}
}
requestAnimationFrame(update);
}
function initCounters() {
const counters = document.querySelectorAll('[data-counter]');
if (!counters.length) return;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
if (entry.isIntersecting && !entry.target.dataset.animated) {
entry.target.dataset.animated = 'true';
const target = parseInt(entry.target.dataset.counter, 10) || 0;
animateCounter(entry.target, target);
}
});
},
{ threshold: 0.6 }
);
counters.forEach(el => observer.observe(el));
}
document.addEventListener('DOMContentLoaded', initCounters);