数字滚动组件:包含千分位
index.vue
<template> <div class="num" :style="'font-size:'+size+'px;'"> <span v-if="minus">-</span> <number-son v-for="(p, i) in intArr" :key="i" :num="p" :time="time" /> <span v-if="fixed > 0">.</span> <number-son v-for="(p, i) in floatArr" :key="i" :num="p" :time="time" /> </div> </template> <script lang="ts"> import { defineComponent, ref, watch, toRefs } from "vue"; import NumberSon from "./NumberSon.vue"; export default defineComponent({ name: "Number", components: { NumberSon, }, props: { num: { type: [Number, String], default: 0, }, //数值 size: { type: Number, default: 28, }, //大小 fixed: { type: Number, default: 0, }, //保留小数位,默认0 thousands: { type: Boolean, default: false, }, //是否添加千分位符,默认false time: { type: Number, default: 400, }, //翻转时间,默认400 }, setup(props) { const { num } = toRefs(props); let fixed: number = Number(props.fixed) || 0; let thousands: boolean = Boolean(props.thousands) || false; let time: any = Number(props.time) > 0 ? ref(Number(props.time)) : 400; let arr: any = []; let floatArr: any = ref([]); let intArr: any = ref([]); let minus: any = ref(false); // 数据处理 let dispose = (data: any) => { if (data < 0) { minus = true; data = -data; } let datas: any = String(data); // 分离整数、小数 if (datas.indexOf(".") != -1) { arr = datas.split("."); floatArr.value = arr[1].split(""); //[string] } else { arr[0] = datas; arr[1] = ""; } intArr.value = arr[0].split(""); // [string] if (thousands == true && intArr.value.length > 3) { // 整数——添加千分位 let k = 0; let b = []; for (let i = 0; i < intArr.value.length; i++) { // 类型转换 b[k] = Number(intArr.value[i]); k++; if ( i < intArr.value.length - 1 && (intArr.value.length - i - 1) % 3 == 0 ) { b[k] = ","; k++; } } intArr.value = b; } else { for (let i = 0; i < intArr.value.length; i++) { intArr.value[i] = Number(intArr.value[i]); } } // 保留小数位数 let a = []; for (let i = 0; i < fixed; i++) { if (floatArr.value[i]) { a[i] = Number(floatArr.value[i]); } else { a[i] = 0; } } floatArr.value = a; }; // 初始化 dispose(num.value); // 监听 watch( num, (newVal, oldVal) => { arr = []; floatArr.value = []; intArr.value = []; minus = false; dispose(newVal); }, { deep: true } ); return { minus, intArr, floatArr, fixed, time }; }, }); </script> <style scoped> .num { /* font-size: 28px; */ } </style>
滚动组件number-scroll:
<template> {{ data }} </template> <script lang="ts"> import { defineComponent, ref, watch, toRefs, onMounted, onUnmounted } from "vue"; export default defineComponent({ name: "Number", props: { num: [Number, String], time: Number, }, setup(props) { const { num } = toRefs(props); const time: any = ref(props.time); let data: any = ref(0); let animation:any; let transition = (num: any) => { // 判断是数字、逗号 if (typeof num == "number") { let lastTime = 0; const val = time.value / num; function transitionInt(time: number) { let interval = time - lastTime; if (interval > val) { lastTime = time; // 整数 if (num == 0) { data.value = data.value; } else { data.value += 1; } } if (data.value < num) { // 形成回调 window.requestAnimationFrame(transitionInt); } } // 启动动画 animation=window.requestAnimationFrame(transitionInt); // 当浏览器切换到后台后,requestAnimationFrame是不会再去执行事件了 } else { data.value = num; } }; onMounted(() => { transition(num.value); }); onUnmounted(()=>{ window.cancelAnimationFrame(animation) }) watch( num, (newVal, oldVal) => { data.value=0; transition(newVal); }, { deep: true } ); return { data }; }, }); </script> <style scoped> .son { display: inline-block; } </style>