1import { Controller } from "@hotwired/stimulus"; 2 3export default class extends Controller { 4 connect() { 5 this.handleTrigger(); 6 } 7 8 handleTrigger() { 9 const trigger = this.element.dataset.animatedNumberTrigger; 10 11 switch (trigger) { 12 case "load": 13 this.animateNumber(); 14 break; 15 case "viewport": 16 this.observeViewport(); 17 break; 18 default: 19 break; 20 } 21 } 22 23 animateNumber() { 24 const startValue = parseInt(this.element.dataset.animatedNumberStartValue) || 0; 25 const endValue = parseInt(this.element.dataset.animatedNumberEndValue); 26 const duration = parseInt(this.element.dataset.animatedNumberDuration) || 2000; 27 28 let currentValue = startValue; 29 const totalSteps = duration / 16; // Assuming 60 FPS (1000ms / 16ms per frame) 30 const increment = (endValue - startValue) / totalSteps; 31 32 const animate = (startTime) => { 33 const elapsedTime = performance.now() - startTime; 34 const progress = Math.min(elapsedTime / duration, 1); 35 currentValue = startValue + increment * (totalSteps * progress); 36 this.element.textContent = Math.ceil(currentValue); // Update the element's text content 37 38 if (progress < 1) { 39 requestAnimationFrame((timestamp) => animate(startTime)); 40 } 41 }; 42 43 requestAnimationFrame(animate); 44 } 45 46 observeViewport() { 47 const observer = new IntersectionObserver((entries) => { 48 entries.forEach((entry) => { 49 if (entry.isIntersecting) { 50 this.animateNumber(); 51 observer.unobserve(this.element); 52 } 53 }); 54 }); 55 56 observer.observe(this.element); 57 } 58};
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.