首页统计栏数字实现数字滚动效果,废话不多说直接上代码:
javascript
// 新增:执行数字滚动动画
runCountAnimation(targetVal) {
// 计算步长(目标值越大,步长越大,保证动画速度均匀)
const step = Math.max(1, Math.ceil(targetVal / 100));
// 设置定时器,实现平滑递增
this.countTimer = setInterval(() => {
// 判断:当前数字未达到目标值,继续递增
if (this.currentCount < targetVal) {
// 防止最后一步超出目标值,取最小值
this.currentCount = Math.min(this.currentCount + step, targetVal);
} else {
// 达到目标值,清理定时器
this.clearCountTimer();
}
}, 16); // 约60帧/秒,保证动画流畅
},
// 新增:清理定时器
clearCountTimer() {
if (this.countTimer) {
clearInterval(this.countTimer);
this.countTimer = null;
}
}
我这个是一个封装的组件,所以上面的执行方法逻辑如下:
javascript
watch: {
// 监听目标count变化,触发数字滚动动画
count(newVal, oldVal) {
// 先清理原有定时器,防止重复触发
this.clearCountTimer();
// 重置当前显示数字为0
this.currentCount = 0;
// 若新值为0,直接结束,不执行动画
if (newVal === 0) return;
// 执行数字滚动动画
this.runCountAnimation(newVal);
}
},
mounted() {
// 组件初始化时,触发一次动画(针对初始传入的count值)
if (this.count !== 0) {
this.runCountAnimation(this.count);
}
},
beforeDestroy() {
// 组件销毁前,清理定时器,防止内存泄露
this.clearCountTimer();
},
组件的完整代码,这个是jeecg boot 3.2.0 的前端项目,该兴趣可以看看,里面使用了j-ellispsis进行数字缩略
javascript
<template>
<a-card :loading="loading" :bordered="false">
<div class="card">
<div class="logo-c" :style="{background:bgColor}">
<img :src="src" class="card-l" />
</div>
<div class="money-content">
<div class="title"><j-ellipsis :value="title" :length="8"/></div>
<div style="white-space: nowrap;">
<!-- 保持原有格式化和省略逻辑,仅替换数据源为currentCount -->
<span class="count" :style="{color:fontColor}">
<j-ellipsis :value="String(formattedCount)" :length="8"/>
</span>
<span class="c-font" style="margin-left: 3px">{{formattedUnit}}</span>
</div>
</div>
</div>
</a-card>
</template>
<script>
export default {
name: "MoneyCode",
props: {
title: {
type: String,
default: ''
},
total: {
type: String,
default: ''
},
loading: {
type: Boolean,
default: false
},
//字体颜色
fontColor:{
type: String,
default: "#FF4D4F"
},
//背景颜色
bgColor:{
type: String,
default: "#FFF1F0"
},
//数量(目标值)
count:{
type: Number,
default: 0
},
//单位
unit:{
type: String,
default: '笔'
},
src:{
default: require("@/assets/day-money-count.svg")
}
},
data() {
return {
currentCount: 0, // 新增:当前动画显示的数字(响应式)
countTimer: null // 新增:定时器实例,用于清理定时器
}
},
computed: {
// 原有逻辑不变,仅将依赖的this.count改为this.currentCount
formattedCount() {
if (this.currentCount >= 10000) {
return (this.currentCount / 10000).toFixed(3);
}
return this.currentCount;
},
formattedUnit() {
// 注意:此处判断目标值count,而非当前动画值currentCount,保证单位格式化准确
if (this.count >= 10000) {
let locale = localStorage.getItem('locale');
if(locale === 'en_GB'){
return 'W ' + this.unit;
}else if(locale === 'vi_VN'){
return 'triệu ' + this.unit;
} else{
return '万' + this.unit;
}
}
return this.unit;
}
},
watch: {
// 监听目标count变化,触发数字滚动动画
count(newVal, oldVal) {
// 先清理原有定时器,防止重复触发
this.clearCountTimer();
// 重置当前显示数字为0
this.currentCount = 0;
// 若新值为0,直接结束,不执行动画
if (newVal === 0) return;
// 执行数字滚动动画
this.runCountAnimation(newVal);
}
},
mounted() {
// 组件初始化时,触发一次动画(针对初始传入的count值)
if (this.count !== 0) {
this.runCountAnimation(this.count);
}
},
beforeDestroy() {
// 组件销毁前,清理定时器,防止内存泄露
this.clearCountTimer();
},
methods: {
// 新增:执行数字滚动动画
runCountAnimation(targetVal) {
// 计算步长(目标值越大,步长越大,保证动画速度均匀)
const step = Math.max(1, Math.ceil(targetVal / 100));
// 设置定时器,实现平滑递增
this.countTimer = setInterval(() => {
// 判断:当前数字未达到目标值,继续递增
if (this.currentCount < targetVal) {
// 防止最后一步超出目标值,取最小值
this.currentCount = Math.min(this.currentCount + step, targetVal);
} else {
// 达到目标值,清理定时器
this.clearCountTimer();
}
}, 16); // 约60帧/秒,保证动画流畅
},
// 新增:清理定时器
clearCountTimer() {
if (this.countTimer) {
clearInterval(this.countTimer);
this.countTimer = null;
}
}
}
}
</script>
使用组件,里面使用了vue-i18n进行国际化,感兴趣的可以了解我之前的文章
https://blog.csdn.net/a_biggerfish/article/details/147423588?spm=1001.2014.3001.5502
javascript
<a-row :gutter="[24,16]">
<a-col :sm="24" :md="12" :xl="6" :xxl="4">
<money-card :title="$t('dashboard.dailyPaymentFrequency')" :unit="$t('dashboard.count')" :count="baseInfo.dayPaymentsCount?baseInfo.dayPaymentsCount:0" :src="require('@/assets/day-money-count.svg')"></money-card>
</a-col>
<a-col v-has="'chart:all'" :sm="24" :md="12" :xl="6" :xxl="4">
<money-card :title="$t('dashboard.dailyPaymentAmount')" :unit="$t('dashboard.RMB')" :count="baseInfo.dayPaymentsMoney?baseInfo.dayPaymentsMoney:0" :src="require('@/assets/day-money-count.svg')"></money-card>
</a-col>
<a-col v-has="'chart:all'" :sm="24" :md="12" :xl="6" :xxl="4">
<money-card :title="$t('dashboard.dailyAccumulatedUsage')" unit="m³" :count="baseInfo.dayWaterVolume?baseInfo.dayWaterVolume:0" font-color="#FFA940" bg-color="#FFF7E6" :src="require('@/assets/day-money.svg')"></money-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :xxl="4">
<money-card :title="$t('dashboard.dailyAccumulatedPayment')" :unit="$t('dashboard.RMB')" :count="baseInfo.dayPaymentsAmount?baseInfo.dayPaymentsAmount:0" font-color="#FFA940" bg-color="#FFF7E6" :src="require('@/assets/day-money.svg')"></money-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :xxl="4">
<money-card :title="$t('dashboard.monthlyPaymentFrequency')" :unit="$t('dashboard.count')" :count="baseInfo.monthPaymentsCount?baseInfo.monthPaymentsCount:0" font-color="#BAE637" bg-color="#F6FFED" :src="require('@/assets/month-money-count.svg')"></money-card>
</a-col>
<a-col v-has="'chart:all'" :sm="24" :md="12" :xl="6" :xxl="4">
<money-card :title="$t('dashboard.monthlyPaymentAmount')" :unit="$t('dashboard.RMB')" :count="baseInfo.monthPaymentsMoney?baseInfo.monthPaymentsMoney:0" font-color="#BAE637" bg-color="#F6FFED" :src="require('@/assets/month-money-count.svg')"></money-card>
</a-col>
<a-col v-has="'chart:all'" :sm="24" :md="12" :xl="6" :xxl="4">
<money-card :title="$t('dashboard.monthlyAccumulatedUsage')" unit="m³" :count="baseInfo.monthWaterVolume?baseInfo.monthWaterVolume:0" font-color="#FADB14" bg-color="#FEFFE6" :src="require('@/assets/month-money.svg')"></money-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :xxl="4">
<money-card :title="$t('dashboard.monthlyAccumulatedPayment')" :unit="$t('dashboard.RMB')" :count="baseInfo.monthPaymentsAmount?baseInfo.monthPaymentsAmount:0" font-color="#FADB14" bg-color="#FEFFE6" :src="require('@/assets/month-money.svg')"></money-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :xxl="4">
<money-card :title="$t('dashboard.monthlyAccountOpeningsNumber')" :unit="$t('dashboard.households')" bg-color="#E6F7FF" font-color="#40A9FF" :count="baseInfo.monthOpenAccountCount?baseInfo.monthOpenAccountCount:0" :src="require('@/assets/month-home.svg')"></money-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :xxl="4">
<money-card :title="$t('dashboard.totalAccountOpeningsNumber')" :unit="$t('dashboard.households')" :count="baseInfo.totalOpenAccountCount?baseInfo.totalOpenAccountCount:0" font-color="#9254DE" bg-color="#F9F0FF" :src="require('@/assets/all-home.svg')"></money-card>
</a-col>
</a-row>
效果如下:
https://live.csdn.net/v/508969
20260106_165126