1.创建组件 DynamicNumbers.vue
<template>
<div class="statistics-num">
<el-tooltip
:content="content"
placement="top"
effect="light"
:disabled="+to < 10000"
class="tooltip"
>
<div v-if="to">
<span class="num">{{ currentNumber.toLocaleString() }}</span>
<span class="num-isHtml" v-show="getTenThousand">{{
isHtml || ""
}}</span>
<span class="num-unit">{{ unit || "" }}</span>
</div>
<div v-else>-</div>
</el-tooltip>
</div>
</template>
<script>
import { floattotwo } from "@/utils";
export default {
name: "DynamicNumbers",
props: {
// 目标数字
to: {
type: [String, Number],
default: () => 0
},
// 动画持续时间(单位:毫秒)
duration: {
type: [String, Number],
default: () => 2000
},
// // 当前数字,初始值为0
currentVal: {
type: [String, Number],
default: () => 0
},
// 动画开始时间
startTime: {
type: [String, Number],
default: () => null
},
unit: {
type: [String, Number],
default: () => ""
},
getTenThousand: {
type: [String, Number, Boolean],
default: () => 10000
}
},
data() {
return {
// 目标数字
endVal: 0,
// 动画持续时间(单位:毫秒)
durations: 2000,
// 当前数字,初始值为0
currentNumber: 0,
// 动画开始时间
animationStartTime: null,
// 过万时,以万为单位展示
isHtml: "",
tenThousand: 10000
};
},
computed: {
content() {
return this.to + " " + this.unit;
}
},
watch: {
to(val) {
this.endVal = val;
},
duration(val) {
this.durations = val;
},
currentVal(val) {
this.currentNumber = val;
},
startTime(val) {
this.animationStartTime = val;
},
getTenThousand: {
deep: true,
handler(val) {
this.tenThousand = val;
console.log(val);
},
immediate: true
}
},
mounted() {
// 在组件挂载后启动数字滚动效果
this.startCount();
},
methods: {
startCount() {
// 使用requestAnimationFrame()方法实现动画效果
window.requestAnimationFrame(timestamp => {
// 如果animationStartTime属性为空,则将当前时间赋值给它
if (!this.animationStartTime) this.animationStartTime = timestamp;
// 计算当前时间与动画开始时间之间的时间差,以及时间差所占总时间的百分比
const progress = timestamp - this.animationStartTime;
const percentage = Math.min(progress / this.durations, 1);
// 根据时间百分比计算当前数字,并将其赋值给currentNumber属性
this.currentNumber = Math.floor(percentage * (this.endVal - 0) + 0);
// 如果动画持续时间还没有达到,则继续循环调用startCount()方法
if (progress < this.durations) {
this.startCount();
}
if (+this.currentNumber >= this.tenThousand) {
let deal_num = parseFloat(+this.currentNumber);
this.isHtml = "万";
this.currentNumber =
deal_num >= this.tenThousand
? floattotwo(2, deal_num / this.tenThousand)
: deal_num;
}
});
}
}
};
</script>
<style></style>
2.页面中使用
<dynamic-numbers
:to="item.num"
:duration="2000"
:unit="item.unit"
class="number"
>
</dynamic-numbers>
3.@/utils 方法
/**
* Parse the time to string
* type is 小数点后几位
* msg为待浮点数或字符串,并为最后返回值
*/
export function floattotwo(type, msg) {
var f = parseFloat(msg);
if (isNaN(f)) {
return "false";
}
switch (type) {
case 0: //整型
var s = parseInt(f);
return s;
// msg = parseFloat(msg);
// return Math.floor(msg * 10) / 10;
break;
case 1: //小数点后一位
var f = Math.round(msg * 10) / 10;
var s = f.toString();
var rs = s.indexOf('.');
if (rs < 0) {
rs = s.length;
s += '.';
}
while (s.length <= rs + 1) {
s += '0';
}
return s;
// msg = parseFloat(msg);
// return Math.floor(msg * 10) / 10;
break;
case 2:
//制保留2位小数,如:2,会在2后面补上00.即2.00
var f = Math.round(msg * 100) / 100;
var s = f.toString();
var rs = s.indexOf('.');
if (rs < 0) {
rs = s.length;
s += '.';
}
while (s.length <= rs + 2) {
s += '0';
}
//msg = parseFloat(msg);
return s;
break;
case 99: //保存原数据,不截取
return msg;
break;
default:
alert("数据类型有误");
return;
}
}