1const DURATION = 2000; 2 3export class AnimateCount { 4 constructor(container, selectorItem) { 5 this.container = container; 6 7 if (!this.container) { 8 console.warn('Not found this.container for class AnimateCount'); 9 return; 10 } 11 12 this.target = parseInt(this.container.dataset.count, 10); 13 14 if (!this.target) return; 15 16 this.items = this.container.querySelectorAll(selectorItem); 17 this.init(); 18 } 19 20 init() { 21 const _this = this; 22 23 const observer = new IntersectionObserver((entries) => { 24 entries.forEach(entry => { 25 if (entry.isIntersecting) { 26 _this.animate(); 27 observer.disconnect(); 28 } 29 }); 30 }, { threshold: 0.3 }); 31 32 observer.observe(this.container); 33 } 34 35 animate() { 36 const start = performance.now(); 37 38 const step = (now) => { 39 const elapsed = now - start; 40 const progress = Math.min(elapsed / DURATION, 1); 41 const eased = 1 - Math.pow(1 - progress, 4); 42 this.updateDigits(Math.round(eased * this.target)); 43 44 if (progress < 1) requestAnimationFrame(step); 45 }; 46 47 requestAnimationFrame(step); 48 } 49 50 updateDigits = (num) => { 51 const str = String(num).padStart(this.items.length, '0'); 52 const digits = str.split('').map(Number); 53 const firstNonZero = digits.findIndex(d => d > 0); 54 const visibleFrom = firstNonZero === -1 ? digits.length - 1 : firstNonZero; 55 56 this.items.forEach((item, i) => { 57 item.textContent = digits[i]; 58 const isLeadingZero = i < visibleFrom && digits[i] === 0; 59 item.classList.toggle('member_zero', isLeadingZero); 60 }); 61 }; 62}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.