number-counter.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // 数字滚动效果 - 使用 Intersection Observer
  2. console.log('Number counter script loaded');
  3. // 数字计数器类
  4. class NumberCounter {
  5. constructor(element) {
  6. this.element = element;
  7. this.target = this.parseTargetNumber();
  8. this.isAnimating = false;
  9. this.hasAnimated = false;
  10. console.log('NumberCounter created for:', this.element.className, 'Target:', this.target);
  11. }
  12. parseTargetNumber() {
  13. const originalText = this.element.textContent.trim();
  14. console.log('Parsing target number from:', originalText);
  15. // 移除逗号并解析数字
  16. const number = parseInt(originalText.replace(/,/g, ''));
  17. if (isNaN(number)) {
  18. console.error('Invalid number:', originalText);
  19. return 0;
  20. }
  21. console.log('Parsed number:', number);
  22. return number;
  23. }
  24. animate(duration = 2000) {
  25. if (this.isAnimating || this.hasAnimated) {
  26. console.log('Animation already running or completed for:', this.element.className);
  27. return;
  28. }
  29. console.log('Starting animation for:', this.element.className, 'Target:', this.target);
  30. this.isAnimating = true;
  31. const start = 0;
  32. const startTime = performance.now();
  33. const update = (currentTime) => {
  34. const elapsed = currentTime - startTime;
  35. const progress = Math.min(elapsed / duration, 1);
  36. // 缓动函数 - easeOutQuart
  37. const easeOutQuart = 1 - Math.pow(1 - progress, 4);
  38. const current = Math.floor(start + (this.target - start) * easeOutQuart);
  39. // 格式化数字(添加千位分隔符)
  40. // const formatted = current.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  41. // this.element.textContent = formatted;
  42. this.element.textContent = current;
  43. if (progress < 1) {
  44. requestAnimationFrame(update);
  45. } else {
  46. // 确保最终显示正确的目标值
  47. // const finalFormatted = this.target.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  48. // this.element.textContent = finalFormatted;
  49. this.element.textContent = this.target;
  50. // 添加动画完成类
  51. this.element.classList.add('animated');
  52. this.isAnimating = false;
  53. this.hasAnimated = true;
  54. console.log('Animation completed for:', this.element.className, 'Final value:', finalFormatted);
  55. }
  56. };
  57. requestAnimationFrame(update);
  58. }
  59. }
  60. // 等待页面加载完成
  61. window.addEventListener('load', function() {
  62. console.log('Window load event fired');
  63. // 查找数字元素
  64. const numberElements = document.querySelectorAll('.number-1, .number-2, .number-3');
  65. console.log('Found number elements:', numberElements.length);
  66. if (numberElements.length === 0) {
  67. console.error('No number elements found!');
  68. return;
  69. }
  70. // 显示原始内容
  71. numberElements.forEach((element, index) => {
  72. console.log(`Element ${index + 1} (${element.className}) original content:`, element.textContent);
  73. });
  74. // 创建数字计数器实例
  75. const counters = Array.from(numberElements).map(element => new NumberCounter(element));
  76. // 创建 Intersection Observer
  77. const observer = new IntersectionObserver((entries) => {
  78. entries.forEach(entry => {
  79. if (entry.isIntersecting) {
  80. console.log('Element entered viewport:', entry.target.className);
  81. // 找到对应的计数器并开始动画
  82. const counter = counters.find(c => c.element === entry.target);
  83. if (counter) {
  84. counter.animate(2000);
  85. }
  86. // 一旦动画开始,就不再观察这个元素
  87. observer.unobserve(entry.target);
  88. }
  89. });
  90. }, {
  91. threshold: 0.5, // 当元素50%可见时触发
  92. rootMargin: '0px 0px -50px 0px' // 稍微提前触发
  93. });
  94. // 开始观察所有数字元素
  95. numberElements.forEach(element => {
  96. observer.observe(element);
  97. console.log('Started observing element:', element.className);
  98. });
  99. });
  100. // 添加全局函数用于手动测试
  101. window.testNumberAnimation = function() {
  102. console.log('Manual test triggered');
  103. const elements = document.querySelectorAll('.number-1, .number-2, .number-3');
  104. elements.forEach((el, i) => {
  105. console.log(`Element ${i + 1}:`, el.textContent);
  106. });
  107. };