<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数字滚动</title>
</head>
<body>
<p id="test"></p>
<script>
class NumberGrow{
constructor(options) {
/**
* options
* @param {value} Number 值,默认为0
* @param {format} Function 格式化文本
* */
if (typeof options.el !== 'object' || !options.el.nodeType) throw('需要传入dom元素');
this.$el = options.el;
this.timer = null;
this.time = +options.time || 1;
this.value = this.newValue = this.pointLength = 0;// 小数点长度
this.format = options.format;
// 开始
this.update(options.value);
}
getStep(value) {
let flag = false;
if (value < 0) {
value = Math.abs(value);
flag = true;
}
value = Math.ceil(value / this.time / 30);// 除以30,放慢一点
return flag ? -value : value;
}
anim(step) {
const absStep = Math.abs(step);
clearInterval(this.timer);
this.timer = setInterval(() => {
this.updateText(this.value += step);
if (Math.abs(this.newValue - this.value) < absStep) {
this.updateText(this.value = this.newValue, false);
clearInterval(this.timer);
}
}, 10);
}
getPointLength(value) {
value += '';
const index = value.lastIndexOf('.');
if (!~index) {
return 0
}
return value.length - index - 1;
}
update(newValue) {
newValue = +newValue || 0; // 尽量只传数字
if (newValue === this.value) return this.updateText(newValue);
this.pointLength = this.getPointLength(newValue);
this.newValue = newValue;
const step = this.getStep(newValue - this.value);
this.anim(step);
}
updateText(value, autoFixPoint = true) {
let newText = value;
if (autoFixPoint && this.pointLength) {
newText = +(value.toFixed(0) + '.' + this.getRandomByPointLength(this.pointLength));
}
if (this.format instanceof Function) {
newText = this.format(newText);
}
this.$el.innerText = newText;
}
getRandomByPointLength(length) {
let maxNum = '', minNum = '1';
let i = 0;
while (i < length) {
maxNum += 9;
minNum += 0;
i++;
}
maxNum = +maxNum;
minNum = +minNum.slice(0, -1);
return Math.ceil(minNum + Math.random() * (maxNum - minNum));
}
destory() {
clearInterval(this.timer);
}
}
const test = new NumberGrow({
el: document.getElementById('test'),
value: 9999999999.3201,
time: 20,
format(num) {
return '¥' + num.toLocaleString();
},
});
setTimeout(() => {
test.update(-9999999999.1235);
}, 1000);
</script>
</body>
</html>