数值更新时的数字滚动动画实现方案咨询
滚动数字计数器实现(带动画+两位小数+逗号分隔)
下面是一套可以直接复用的实现代码,能实现数值更新时的滚动动画,满足你要求的保留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>
核心逻辑说明:
HTML部分:
- 主容器包含计数器和测试按钮,初始目标值通过
data-target设置 - 按钮用于触发数值更新,验证滚动动画效果
- 主容器包含计数器和测试按钮,初始目标值通过
CSS部分:
- 单个数字位
.digit设置overflow:hidden,只显示当前数字 .digits-list包含0-9所有数字,通过transform: translateY()实现滚动,transition属性保证动画平滑- 逗号单独做样式处理,和数字底部对齐
- 单个数字位
JS部分:
RollingCounter类封装了所有逻辑,包括数值解析、格式化、DOM渲染和动画控制updateTarget方法用于外部触发数值更新,自动执行滚动动画- 自动处理位数补全(比如从0000.00滚动到1234.56)
内容的提问来源于stack exchange,提问作者Eu Román
相关产品推荐
相关产品推荐

