| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- import { defineComponent, ref, watch, onMounted, computed } from "vue";
- const props = {
- startVal: {
- type: Number,
- default: 0
- },
- endVal: {
- type: Number,
- default: 2021
- },
- duration: {
- type: Number,
- default: 3000
- },
- autoplay: {
- type: Boolean,
- default: true
- },
- decimals: {
- type: Number,
- default: 0
- },
- separator: {
- type: String,
- default: ","
- },
- prefix: {
- type: String,
- default: ""
- },
- suffix: {
- type: String,
- default: ""
- },
- fontSize: {
- type: String,
- default: "16px"
- },
- color: {
- type: String,
- default: ""
- }
- };
- export const ReNormalCountTo = defineComponent({
- name: "ReNormalCountTo",
- props,
- emits: ["mounted", "callback"],
- setup(props, { emit }) {
- const state = ref(props.startVal);
- const startTime = ref(0);
- const rafId = ref(0);
- const formatNumber = computed(() => {
- const val = state.value.toFixed(props.decimals);
- const parts = val.split(".");
- parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, props.separator);
- return props.prefix + parts.join(".") + props.suffix;
- });
- function count(timestamp: number) {
- if (!startTime.value) startTime.value = timestamp;
- const progress = timestamp - startTime.value;
- const remaining = props.duration - progress;
- if (remaining < 0) {
- state.value = props.endVal;
- emit("callback");
- return;
- }
- const rate = progress / props.duration;
- state.value = props.startVal + (props.endVal - props.startVal) * rate;
- rafId.value = requestAnimationFrame(count);
- }
- function start() {
- startTime.value = 0;
- rafId.value = requestAnimationFrame(count);
- }
- onMounted(() => {
- if (props.autoplay) {
- start();
- }
- emit("mounted");
- });
- watch(
- () => props.endVal,
- () => {
- if (props.autoplay) {
- start();
- }
- }
- );
- return () => (
- <span
- style={{
- fontSize: props.fontSize,
- color: props.color
- }}
- >
- {formatNumber.value}
- </span>
- );
- }
- });
- export default ReNormalCountTo;
|