样式用的是windicss
代码
<template>
<div class="w-full flex justify-center items-center">
<div
v-for="(item, index) in numList"
:key="index"
class="num-item w-32px h-42px text-26px text-center border border-hex-8fbbff rounded leading-42px"
>
<div v-for="(child, childIndex) in 10" :key="childIndex" :style="{ ...style(item) }">
{{ childIndex }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, watch } from 'vue'
const props = defineProps({
number: {
type: Number,
default: 0
},
// 位数
quantity: {
type: Number,
default: 5
},
// 是否从零开始变化
delayed: {
type: Boolean,
default: true
},
// 过度时间
time: {
type: Number,
default: 2000
},
// 过度动画速度
timing: {
type: String,
default: 'ease'
}
})
const num = ref(0)
const numArr = computed(() => {
if (num.value) {
return (num.value + '').split('')
} else {
return new Array(num.value.length).fill(0)
}
})
const numList = computed(() => {
let arr = []
let len = numArr.value.length
if (props.quantity && props.quantity > len) {
arr = [...new Array(props.quantity - len).fill(0), ...numArr.value]
} else {
arr = numArr.value
}
return arr
})
watch(
() => props.number,
(newValue, oldValue) => {
num.value = newValue
}
)
const style = (e: any) => {
return {
transform: `translateY(-${e * 100}%)`,
transition: props.time + 'ms',
transitionTimingFunction: props.timing
}
}
onMounted(() => {
if (props.delayed) {
setTimeout(() => {
num.value = props.number
}, 300)
} else {
num.value = props.number
}
})
</script>
<style lang="scss" scoped>
.num-item {
background-image: linear-gradient(180deg, #493fffad 0%, #194ccfb3 100%);
overflow: hidden;
font-family: Impact;
text-shadow: 0 2px 4px #0000002e;
margin-right: 12px;
&:last-child {
margin-right: 0;
}
}
</style>