1document.addEventListener('DOMContentLoaded', () => { 2 const rollingNumberBlocks = document.querySelectorAll('.block-numbers'); 3 4 const rollingNumberBlockObserver = new IntersectionObserver((entries) => { 5 const animationDuration = 2000; 6 // Calculate how long each âframeâ should last if we want to update the animation 60 times per second 7 const frameDuration = 1000 / 60; 8 // Use that to calculate how many frames we need to complete the animation 9 const totalFrames = Math.round( animationDuration / frameDuration ); 10 // An ease-out function that slows the count as it progresses 11 const easeOutQuad = t => t * ( 2 - t ); 12 13 const animateCountUp = el => { 14 if (el.dataset.animating === 'true') { 15 return; 16 } 17 18 el.dataset.animating = 'true'; 19 20 const originalValue = el.innerHTML; 21 const countTo = parseFloat(originalValue.replace(',', '.')); 22 23 if (isNaN(countTo)) { 24 el.dataset.animating = 'false'; 25 return; 26 } 27 28 const isInteger = Number.isInteger(countTo); 29 const decimalPlaces = isInteger ? 0 : (originalValue.split(',')[1]?.length || 2); 30 31 let frame = 0; 32 33 // Start the animation running 60 times per second 34 const counter = setInterval( () => { 35 frame++; 36 // Calculate our progress as a value between 0 and 1 37 // Pass that value to our easing function to get our 38 // progress on a curve 39 const progress = easeOutQuad( frame / totalFrames ); 40 // Use the progress value to calculate the current count 41 const currentCount = countTo * progress; 42 43 // If the current count has changed, update the element 44 if (parseFloat(el.innerHTML.replace(',', '.')) !== currentCount) { 45 const formattedCount = isInteger 46 ? Math.round(currentCount) 47 : currentCount.toFixed(decimalPlaces).replace('.', ','); 48 el.innerHTML = formattedCount; 49 } 50 51 // If weâve reached our last frame, stop the animation 52 if ( frame === totalFrames ) { 53 clearInterval( counter ); 54 el.dataset.animating = 'false'; 55 } 56 }, frameDuration ); 57 } 58 59 // Loop over the entries 60 entries.forEach((entry) => { 61 // If the element is visible 62 if (entry.isIntersecting) { 63 // Add the animation class 64 entry.target.classList.add('reveal'); 65 66 const numbers = entry.target.querySelectorAll('.rolling-number'); 67 68 numbers.forEach(animateCountUp); 69 } 70 }); 71 }, { threshold: 0.5 }); 72 73 rollingNumberBlocks.forEach((el) => { 74 rollingNumberBlockObserver.observe(el); 75 }); 76 77});
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.