All files / src/components/u-countup.vue index.vue

68.42% Statements 13/19
33.33% Branches 2/6
33.33% Functions 1/3
72.22% Lines 13/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161      7x   7x     7x                                                                                                                                                                                                                                                                                                                
<template>
<span :class="$style.root">
    <span :class="$style.count">
        <span ref="count">{{ start }}</span>
        <span>{{ unitText }}</span>
    </span>
    <slot></slot>
</span>
</template>
 
<script>
import Countup from 'countup.js';
 
export default {
    name: 'u-countup',
    props: {
        start: { type: Number, default: 0 },
        end: { type: Number, required: true },
        simplify: { type: Boolean, default: false },
        duration: { type: Number, default: 2 },
        isEasing: { type: Boolean, default: false },
        isGroup: { type: Boolean, default: false },
        separator: { type: String, default: ',' },
        decimals: { type: Number, default: 0 }, // decimal: {
        //     type: String,
        //     default: '.',
        // },
        unit: {
            type: Array,
            default: () => [
                [3, 'K+'],
                [6, 'M+'],
                [9, 'G+'],
            ],
        },
        prefix: { type: String, default: '' },
        suffix: { type: String, default: '' },
        easingFn: {
            type: Function,
            default(t, b, c, d) {
                return (
                    (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b
                );
            },
        },
        endCallback: { type: Function },
        autoStart: { type: Boolean, default: true }, // formattingFn: {
        //     type: Function,
        //     default() {
        //     },
        // },
    },
    data() {
        return { unitText: '' };
    },
    watch: {
        end(newValue) {
            let endVal = 0;
            if (this.simplify) {
                const res = this.transformValue(newValue);
                endVal = res.val;
                this.unitText = res.unit;
            } else {
                endVal = newValue;
            }
            if (this.autoStart)
                this.counter.update(endVal);
        },
        autoStart(newValue) {
            if (newValue) {
                this.counter.start(this.endCallback); // 暂不支持change方法 需要重构下
                // this.$emit('change', this.counter.frameVal);
            }
        },
    },
    mounted() {
        this.$nextTick(() => {
            let end = 0;
            let res = {};
            if (this.simplify) {
                res = this.transformValue(this.end);
                end = res.val;
                this.unitText = res.unit;
            } else {
                end = this.end;
            }
            this.counter = new Countup(
                this.$refs.count,
                this.start,
                end,
                this.decimals,
                this.duration,
                {
                    useEasing: this.isEasing,
                    useGrouping: this.isGroup,
                    separator: this.separator,
                    decimals: this.decimals,
                    suffix: this.suffix,
                    prefix: this.prefix,
                },
            );
            if (!this.counter.error && this.autoStart) {
                this.counter.start(this.endCallback); // this.$emit('change', this.counter.frameVal);
            }
        });
    },
    methods: {
        transformValue(val) {
            let endVal = 0;
            let unit = '';
            const len = this.unit.length;
            if (val < Math.pow(10, this.unit[0][0])) {
                endVal = val;
            } else {
                for (let i = 1; i < len; i++) {
                    if (
                        val >= Math.pow(10, this.unit[i - 1][0])
                        && val < Math.pow(10, this.unit[i][0])
                    ) {
                        endVal = parseInt(
                            val / Math.pow(10, this.unit[i - 1][0]),
                        );
                        unit = this.unit[i - 1][1];
                    }
                }
            }
            if (val > Math.pow(10, this.unit[len - 1][0])) {
                endVal = parseInt(val / Math.pow(10, this.unit[len - 1][0]));
                unit = this.unit[len - 1][1];
            }
            return { val: endVal, unit };
        },
        reset() {
            this.counter.reset();
            this.$emit('reset', this.start);
        },
        pauseResume() {
            this.counter.pauseResume();
            this.$emit('pauseResume', this.counter.frameVal);
        },
        update(value) {
            this.counter.update(value || this.end);
            this.$emit('update', value || this.end);
        },
    },
};
</script>
 
<style module>
.root {
    display: inline-block;
}
.count {
    font-size: 36px;
    line-height: 1;
    width: 0.7em;
    height: 1em;
    color: var(--brand-primary);
}
</style>