效果展示:
代码:
<template>
<div class="counter-container">
<div v-for="(item, index) in numArr" :key="index" :class="item === ',' || item === '.' ? 'mark-item' : 'num-item'">
<span class="pointer" v-if="item == ',' || item == '.'">{{ item }}</span>
<span ref="numberItem" v-else class="num">
{{ flipNum }}
</span>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch, nextTick, onMounted } from "vue";
const props = defineProps({
num: {
type: Number,
default: 0
},
duration: {
type: Number,
default: 1
}
});
let numArr = ref(["0", "0", ",", "0", "0", "0", ",", "0", "0", "0"]);
const flipNum = "0123456789";
// let timer = null;
const numberItem = ref<Array<HTMLSpanElement> | null>(null);
// 处理传递过来的数字,转化为数组
function numToArr() {
const str = props.num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
numArr.value = str.split("");
}
function rollNum() {
const numItems = numberItem.value;
const numberArr = numArr.value.filter(item => item !== "," && item !== ".");
numberArr.forEach((item, index) => {
const num = parseInt(item);
if (numItems) {
const numItem = numItems[index];
numItem.style.transform = `translate(-50%, -${num * 10}%)`;
}
});
}
// 监听数字变化,更新数字
const initNumber = () => {
numToArr();
nextTick(() => {
setTimeout(() => {
rollNum();
}, props.duration * 1000);
});
};
watch(
() => props.num,
() => {
initNumber();
}
);
onMounted(() => {
initNumber();
});
</script>
<style lang="scss" scoped>
.counter-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.counter-container .num-item {
position: relative;
box-sizing: border-box;
width: 22px;
height: 34px;
padding: 8px;
margin-left: 4px;
overflow: hidden;
font-size: 20px;
font-weight: bold;
color: #ffffff;
text-align: center;
background-image: url("@/assets/images/dataBoard/num_wrap.png");
background-repeat: no-repeat;
background-size: 100% 100%;
}
.counter-container .mark-item {
height: 34px;
margin-left: 4px;
font-size: 24px;
font-weight: 800;
line-height: 38px;
color: #ffffff;
text-align: center;
}
.counter-container .num {
position: absolute;
top: 6px;
left: 50%;
letter-spacing: 8px;
writing-mode: vertical-lr;
transition: all 1s ease-in-out;
transform: translate(-50%, 0);
text-orientation: upright;
}
</style>