monacousa-portal/components/CountUp.vue

70 lines
1.3 KiB
Vue
Raw Normal View History

<template>
<span>{{ prefix }}{{ displayValue }}{{ suffix }}</span>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue'
const props = defineProps({
endVal: {
type: Number,
required: true
},
duration: {
type: Number,
default: 2
},
prefix: {
type: String,
default: ''
},
suffix: {
type: String,
default: ''
},
decimals: {
type: Number,
default: 0
}
})
const displayValue = ref(0)
const countUp = () => {
const startTime = Date.now()
const startVal = 0
const endVal = props.endVal
const duration = props.duration * 1000
const updateCount = () => {
const now = Date.now()
const progress = Math.min((now - startTime) / duration, 1)
// Easing function for smooth animation
const easeOutQuart = 1 - Math.pow(1 - progress, 4)
const currentVal = startVal + (endVal - startVal) * easeOutQuart
displayValue.value = props.decimals > 0
? currentVal.toFixed(props.decimals)
: Math.round(currentVal).toLocaleString()
if (progress < 1) {
requestAnimationFrame(updateCount)
} else {
displayValue.value = props.decimals > 0
? endVal.toFixed(props.decimals)
: endVal.toLocaleString()
}
}
updateCount()
}
onMounted(() => {
countUp()
})
watch(() => props.endVal, () => {
countUp()
})
</script>