You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数值更新时的数字滚动动画实现方案咨询

滚动数字计数器实现(带动画+两位小数+逗号分隔)

下面是一套可以直接复用的实现代码,能实现数值更新时的滚动动画,满足你要求的保留2位小数、用英文逗号做小数分隔的需求:

<div class="counter-container">
  <div class="counter" id="numberCounter" data-target="9876.54"></div>
  <button onclick="updateCounter(1234.56)">更新为1234.56</button>
  <button onclick="updateCounter(5678.90)">更新为5678.90</button>
</div>

<style>
.counter-container {
  display: flex;
  align-items: center;
  gap: 1rem;
  font-family: monospace;
  font-size: 2rem;
  margin: 2rem;
}

.counter {
  display: flex;
  align-items: flex-end;
  gap: 0.2rem;
}

.digit {
  width: 1.2rem;
  height: 2rem;
  overflow: hidden;
  position: relative;
  border-bottom: 2px solid #333;
  background-color: #fff;
}

.digits-list {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  transition: transform 0.5s ease-in-out;
}

.digits-item {
  height: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.decimal-separator {
  height: 2rem;
  display: flex;
  align-items: flex-end;
  padding-bottom: 0.2rem;
}
</style>

<script>
class RollingCounter {
  constructor(element) {
    this.element = element;
    this.currentValue = 0;
    this.targetValue = this.parseTargetValue(element.dataset.target);
    this.init();
    this.rollToTarget();
  }

  parseTargetValue(valueStr) {
    // 处理逗号分隔的小数,转成标准数字格式
    return parseFloat(valueStr.replace(',', '.')) || 0;
  }

  formatValue(value) {
    // 保留两位小数,替换小数点为英文逗号
    return value.toFixed(2).replace('.', ',');
  }

  splitValueIntoDigits(value) {
    const formatted = this.formatValue(value);
    return formatted.split('');
  }

  init() {
    const initialDigits = this.splitValueIntoDigits(0);
    this.renderDigits(initialDigits);
  }

  renderDigits(digits) {
    this.element.innerHTML = '';
    digits.forEach(char => {
      if (char === ',') {
        const separator = document.createElement('span');
        separator.className = 'decimal-separator';
        separator.textContent = ',';
        this.element.appendChild(separator);
      } else {
        const digitContainer = document.createElement('div');
        digitContainer.className = 'digit';
        
        const digitsList = document.createElement('div');
        digitsList.className = 'digits-list';
        
        for (let i = 0; i <= 9; i++) {
          const digitItem = document.createElement('div');
          digitItem.className = 'digits-item';
          digitItem.textContent = i;
          digitsList.appendChild(digitItem);
        }
        
        digitContainer.appendChild(digitsList);
        this.element.appendChild(digitContainer);
      }
    });
  }

  rollToTarget() {
    const formattedTarget = this.formatValue(this.targetValue);
    const targetDigits = formattedTarget.split('');
    const digitElements = this.element.querySelectorAll('.digit');
    
    targetDigits.forEach((char, index) => {
      if (char === ',') return;
      
      // 跳过逗号元素,匹配对应数字位的容器
      const separatorCount = targetDigits.slice(0, index).filter(c => c === ',').length;
      const digitEl = digitElements[index - separatorCount];
      const digitsList = digitEl.querySelector('.digits-list');
      const targetNum = parseInt(char);
      
      // 每个数字占2rem高度,计算滚动距离
      digitsList.style.transform = `translateY(-${targetNum * 2}rem)`;
    });
    
    this.currentValue = this.targetValue;
  }

  updateTarget(newValue) {
    this.targetValue = this.parseTargetValue(newValue);
    this.rollToTarget();
  }
}

// 初始化计数器
const counterElement = document.getElementById('numberCounter');
const rollingCounter = new RollingCounter(counterElement);

// 外部调用的更新函数
function updateCounter(newValue) {
  rollingCounter.updateTarget(newValue);
}
</script>

核心逻辑说明:

  1. HTML部分:

    • 主容器包含计数器和测试按钮,初始目标值通过data-target设置
    • 按钮用于触发数值更新,验证滚动动画效果
  2. CSS部分:

    • 单个数字位.digit设置overflow:hidden,只显示当前数字
    • .digits-list包含0-9所有数字,通过transform: translateY()实现滚动,transition属性保证动画平滑
    • 逗号单独做样式处理,和数字底部对齐
  3. JS部分:

    • RollingCounter类封装了所有逻辑,包括数值解析、格式化、DOM渲染和动画控制
    • updateTarget方法用于外部触发数值更新,自动执行滚动动画
    • 自动处理位数补全(比如从0000.00滚动到1234.56)

内容的提问来源于stack exchange,提问作者Eu Román

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 11:45:25