前言
当做数字大屏的时候,就需要做一个数字传入后,可以自增长的组件,可以根据数据大小算每一次跳动的数字
运行效果
会从0开始自动增加到9000(录屏好麻烦)
HTML
<template>
<div class="counter">
<div :style="{ color: fontColor, fontSize: fontSize }">
<span
class="num"
:class="{ cursor: isClickable ? 'pointer' : 'default' }"
@click="handleClick"
>
{{ currentValue }}
</span>
</div>
</div>
</template>
JS
<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
// 定义 props 类型
const props = defineProps<{
// 目标值
target: number;
// 动画时长,默认 3000 毫秒
duration?: number;
// 字体颜色,默认值 'black'
fontColor?: string;
// 字体大小,默认值 '2rem'
fontSize?: string;
// 是否允许点击重新开始动画,默认为 false
clickable?: boolean;
}>();
// 响应式变量 currentValue
const currentValue = ref<number>(0);
// 用来控制动画是否正在进行的变量
let intervalId: ReturnType<typeof setInterval> | null = null;
// 控制是否可以点击
const isClickable = ref<boolean>(props.clickable ?? true);
// 动画更新函数
const animateCounter = () => {
const targetValue = props.target;
const duration = props.duration ?? 3000;
// 计算每次更新的增量,确保增量不会过小
let step = targetValue / (duration / 10);
if (step < 1) step = 1; // 确保最小步长为1
// 清除之前的动画
if (intervalId) {
clearInterval(intervalId);
}
intervalId = setInterval(() => {
currentValue.value += step;
// 保证 currentValue 永远是整数
currentValue.value = Math.floor(currentValue.value); // 使用 Math.floor 确保值是整数
// 如果 currentValue 超过了 targetValue,直接设为 targetValue
if (currentValue.value >= targetValue) {
currentValue.value = targetValue;
clearInterval(intervalId!);
}
}, 10); // 每 10 毫秒更新一次
};
// 处理点击事件,重新开始动画
const handleClick = () => {
if (isClickable.value) {
currentValue.value = 0;
animateCounter();
}
};
// 在组件挂载时启动动画
onMounted(() => {
animateCounter();
});
// 在组件卸载前清除定时器
onBeforeUnmount(() => {
if (intervalId) {
clearInterval(intervalId);
}
});
// 在组件的 target 更新时重新启动动画
watch(
() => props.target,
() => {
currentValue.value = 0;
animateCounter();
},
{ immediate: true }
);
</script>
CSS
<style scoped>
.counter {
font-family: Arial, sans-serif;
}
.num {
font-weight: bold;
cursor: pointer;
}
.num.clickable {
cursor: pointer;
}
</style>
组件使用
<increasing-number
:target="1000"
:duration="2000"
:fontColor="'red'"
:fontSize="'1.5rem'"
:clickable=true
/>
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
target | 数字 | number | - |
duration | 动画完成时间 | number | 3000 |
fontColor | 字体颜色 | string | black |
fontSize | 字体大小 | string | 2rem |
clickable | 是否可点击数字重新开始动画 | boolean | false |