1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
| <script setup lang="ts">
| 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,
| endValue: 2021,
| duration: 1500,
| autoplay: true,
| decimals: 0,
| prefix: '',
| suffix: '',
| separator: ',',
| decimal: '.',
| useEasing: true,
| transition: 'linear'
| });
|
| const source = ref(props.startValue);
|
| const transition = computed(() => (props.useEasing ? TransitionPresets[props.transition] : undefined));
|
| const outputValue = useTransition(source, {
| disabled: false,
| 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;
| }
|
| async function start() {
| await nextTick();
| source.value = props.endValue;
| }
|
| watch(
| [() => props.startValue, () => props.endValue],
| () => {
| if (props.autoplay) {
| start();
| }
| },
| { immediate: true }
| );
| </script>
|
| <template>
| <span>{{ value }}</span>
| </template>
|
| <style scoped></style>
|
|