<script>
// ==============================================
// GSAP Number Counter Animation
// ==============================================
document.addEventListener('DOMContentLoaded', function() {
// ============================================
// Check for GSAP and ScrollTrigger
// ============================================
if (typeof gsap === 'undefined') return;
gsap.registerPlugin(ScrollTrigger);
// ============================================
// DOM Element Selection
// ============================================
const counters = document.querySelectorAll('[data-count]');
if (!counters.length) return;
// ============================================
// Configuration
// ============================================
const CONFIG = {
defaultDuration: 2,
defaultStart: 0,
ease: "power2.out",
triggerStart: "top 85%"
};
// ============================================
// Utility Functions
// ============================================
function getDecimalPlaces(numString) {
const normalized = numString.replace(',', '.');
const parts = normalized.split('.');
if (parts.length > 1) {
return parts[1].length;
}
return 0;
}
function parseNumber(numString) {
const normalized = numString.replace(',', '.');
return parseFloat(normalized);
}
function formatNumber(num, decimals, useComma) {
const formatted = num.toFixed(decimals);
if (useComma) {
return formatted.replace('.', ',');
}
return formatted;
}
// ============================================
// Process each counter
// ============================================
counters.forEach(function(element) {
// Get target number from attribute
const targetString = element.getAttribute('data-count');
if (!targetString) return;
// Parse configuration
const targetNumber = parseNumber(targetString);
const startNumber = parseNumber(element.getAttribute('data-count-start') || String(CONFIG.defaultStart));
const duration = parseFloat(element.getAttribute('data-count-duration') || CONFIG.defaultDuration);
const decimals = getDecimalPlaces(targetString);
const useComma = targetString.includes(',');
// Validate target number
if (isNaN(targetNumber)) return;
// Set initial value
element.textContent = formatNumber(startNumber, decimals, useComma);
// Counter object for GSAP
const counter = { value: startNumber };
// Create ScrollTrigger animation
gsap.to(counter, {
value: targetNumber,
duration: duration,
ease: CONFIG.ease,
scrollTrigger: {
trigger: element,
start: CONFIG.triggerStart,
once: true
},
onUpdate: function() {
element.textContent = formatNumber(counter.value, decimals, useComma);
}
});
});
});
</script>