Geri Dön

Animasyonlu İstatistik Sayacı

İlerleme Çubukları (0-100) / 3 Görüntülenme

Favoriye Ekle

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));