Canlı Önizleme
0
Aktif Kullanıcı
0
Kopyalanan Script
0
Memnuniyet %
Nasıl Kullanılır?
IntersectionObserver sayaç animasyonunu yalnızca element ekranda göründüğünde başlatır. 'data-target' ile hedef değeri HTML'de belirleyin — JS değiştirmeye gerek yok.
Kaynak Kodlar
HTML
<div class="stats-grid">
<div class="stat-box">
<i class="fas fa-users" style="color:#6C5CE7"></i>
<div class="stat-num" data-target="12847">0</div>
<div class="stat-lbl">Aktif Kullanıcı</div>
</div>
<div class="stat-box">
<i class="fas fa-code" style="color:#00cec9"></i>
<div class="stat-num" data-target="4320">0</div>
<div class="stat-lbl">Kopyalanan Script</div>
</div>
<div class="stat-box">
<i class="fas fa-star" style="color:#fdcb6e"></i>
<div class="stat-num" data-target="98">0</div>
<div class="stat-lbl">Memnuniyet %</div>
</div>
</div>
CSS
.stats-grid {
display: flex; gap: 20px; flex-wrap: wrap; font-family: 'Inter', sans-serif;
}
.stat-box {
background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08);
border-radius: 16px; padding: 25px 30px; text-align: center;
min-width: 140px; transition: 0.3s; position: relative; overflow: hidden;
}
.stat-box::before {
content: ''; position: absolute; inset: 0;
background: radial-gradient(circle at 50% 0%, rgba(108,92,231,0.08), transparent 70%);
}
.stat-box:hover {
transform: translateY(-5px);
border-color: rgba(108,92,231,0.4);
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
}
.stat-box i { font-size: 28px; margin-bottom: 12px; display: block; }
.stat-num {
font-size: 38px; font-weight: 800; color: #fff;
margin-bottom: 6px; line-height: 1;
}
.stat-lbl { color: #a0a0b0; font-size: 13px; font-weight: 500; }
JavaScript
function animateCounter(el) {
const target = parseInt(el.getAttribute('data-target'));
const duration = 2000;
const start = performance.now();
function update(now) {
const elapsed = now - start;
const progress = Math.min(elapsed / duration, 1);
// Ease out cubic
const eased = 1 - Math.pow(1 - progress, 3);
el.textContent = Math.floor(eased * target).toLocaleString('tr-TR');
if (progress < 1) requestAnimationFrame(update);
}
requestAnimationFrame(update);
}
// IntersectionObserver ile görünür olunca başlat
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.querySelectorAll('.stat-num').forEach(animateCounter);
observer.unobserve(entry.target);
}
});
}, { threshold: 0.3 });
document.querySelectorAll('.stats-grid').forEach(el => observer.observe(el));