ruoyi-plus-soybean/src/components/custom/count-to.vue

89 lines
1.8 KiB
Vue
Raw Normal View History

<script setup lang="ts">
2024-01-25 23:16:12 +08:00
import { computed, nextTick, ref, watch } from 'vue';
import { TransitionPresets, useTransition } from '@vueuse/core';
defineOptions({
name: 'CountTo'
});
interface Props {
startValue?: number;
endValue?: number;
duration?: number;
autoplay?: boolean;
decimals?: number;
prefix?: string;
suffix?: string;
separator?: string;
decimal?: string;
useEasing?: boolean;
transition?: keyof typeof TransitionPresets;
}
const props = withDefaults(defineProps<Props>(), {
startValue: 0,
2024-01-25 23:16:12 +08:00
endValue: 2021,
duration: 1500,
autoplay: true,
decimals: 0,
prefix: '',
suffix: '',
separator: ',',
2024-01-25 23:16:12 +08:00
decimal: '.',
useEasing: true,
transition: 'linear'
});
2024-01-25 23:16:12 +08:00
const source = ref(props.startValue);
const transition = computed(() => (props.useEasing ? TransitionPresets[props.transition] : undefined));
const outputValue = useTransition(source, {
disabled: false,
2024-01-25 23:16:12 +08:00
duration: props.duration,
transition: transition.value
});
const value = computed(() => formatValue(outputValue.value));
function formatValue(num: number) {
const { decimals, decimal, separator, suffix, prefix } = props;
let number = num.toFixed(decimals);
number = String(number);
const x = number.split('.');
let x1 = x[0];
const x2 = x.length > 1 ? decimal + x[1] : '';
const rgx = /(\d+)(\d{3})/;
if (separator) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, `$1${separator}$2`);
}
}
return prefix + x1 + x2 + suffix;
}
2024-01-25 23:16:12 +08:00
async function start() {
await nextTick();
source.value = props.endValue;
}
watch(
[() => props.startValue, () => props.endValue],
() => {
if (props.autoplay) {
2024-01-25 23:16:12 +08:00
start();
}
},
{ immediate: true }
);
</script>
<template>
<span>{{ value }}</span>
</template>
<style scoped></style>