累計制作実績
<!-- data-to:目標値 / data-dur:所要ミリ秒 --> <div class="bnto-cnt"> <span class="num" data-bnto-count data-to="1280" data-dur="1600">0</span><span class="unit">件</span> <p class="lbl">累計制作実績</p> </div>
.bnto-cnt { --c1: hsl(34 57% 48%); /* 数字の色 */ background: #fff; border: 2px solid #DFE9F1; border-radius: 14px; padding: 22px 18px 18px; text-align: center; } .bnto-cnt .num { font-size: 40px; font-weight: 900; color: var(--c1); line-height: 1; /* 桁が変わっても幅がガタつかない等幅数字 */ font-variant-numeric: tabular-nums; } .bnto-cnt .unit { font-size: 15px; font-weight: 800; margin-left: 3px; } .bnto-cnt .lbl { margin: 8px 0 0; font-size: 12px; font-weight: 700; color: #5A6B7A; }
// 画面に入ったら data-to の値まで 0 からカウントアップ(複数設置OK) // プレビューをクリックすると値をリセットして再生し直します (function () { document.querySelectorAll('[data-bnto-count]').forEach(function (el) { if (el.dataset.bntoInit) return; el.dataset.bntoInit = '1'; var to = parseFloat(el.dataset.to || '100'); var dur = parseInt(el.dataset.dur || '1600', 10); var raf = null; function play() { cancelAnimationFrame(raf); // 再生中なら止めてやり直し var t0 = null; el.textContent = '0'; function step(ts) { if (!t0) t0 = ts; var p = Math.min((ts - t0) / dur, 1); var e = 1 - Math.pow(1 - p, 3); // easeOut:終盤で減速 el.textContent = Math.round(to * e); if (p < 1) raf = requestAnimationFrame(step); } raf = requestAnimationFrame(step); } new IntersectionObserver(function (entries, obs) { if (!entries[0].isIntersecting) return; obs.disconnect(); // 初回は見えた瞬間に一度だけ play(); }, { threshold: 0.5 }).observe(el); // クリックでもう一度再生 var wrap = el.closest('.bnto-cnt') || el; wrap.style.cursor = 'pointer'; wrap.addEventListener('click', play); }); })();
使い方のコツ
目標値は data-to、所要時間は data-dur(ミリ秒)で個別に指定できます。「実績◯件」「満足度◯%」など、数字を並べるときは1〜2秒でサッと終わらせるのが心地よい目安です。プレビューをクリック(または ↺ ボタン)で再生し直せます。