forked from izu/student-web-if-development-kit
refactor(tapops): modularize page code
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
export class CounterAnimation {
|
||||
static DURATION_MS = 2000;
|
||||
|
||||
init() {
|
||||
const counters = document.querySelectorAll('.counter-value[data-target]');
|
||||
if (counters.length === 0) return;
|
||||
|
||||
if ('IntersectionObserver' in window) {
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
this._animate(entry.target);
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.2 });
|
||||
counters.forEach(c => observer.observe(c));
|
||||
} else {
|
||||
counters.forEach(c => this._animate(c));
|
||||
}
|
||||
}
|
||||
|
||||
_animate(el) {
|
||||
const target = Number.parseInt((el.dataset.target || '0').replace(/[^0-9]/g, ''), 10);
|
||||
if (Number.isNaN(target)) return;
|
||||
CounterAnimation.animateValue(el, target, el.dataset.suffix || '');
|
||||
}
|
||||
|
||||
// Reusable easing tween from 0 → target. Callable for stats whose
|
||||
// value is only known after an async fetch (no data-target needed).
|
||||
static animateValue(el, target, suffix = '') {
|
||||
if (!el || Number.isNaN(target)) return;
|
||||
const startTime = performance.now();
|
||||
|
||||
const tick = (now) => {
|
||||
const progress = Math.min((now - startTime) / CounterAnimation.DURATION_MS, 1);
|
||||
const eased = 1 - Math.pow(1 - progress, 3);
|
||||
el.textContent = Math.floor(eased * target) + suffix;
|
||||
if (progress < 1) requestAnimationFrame(tick);
|
||||
else el.textContent = target + suffix;
|
||||
};
|
||||
requestAnimationFrame(tick);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user