vue3封装数字滚动组件

效果展示:

代码:

<template>
	<div class="counter-container">
		<div v-for="(item, index) in numArr" :key="index" :class="item === ',' || item === '.' ? 'mark-item' : 'num-item'">
			<span class="pointer" v-if="item == ',' || item == '.'">{{ item }}</span>
			<span ref="numberItem" v-else class="num">
				{{ flipNum }}
			</span>
		</div>
	</div>
</template>

<script setup lang="ts">
import { ref, watch, nextTick, onMounted } from "vue";

const props = defineProps({
	num: {
		type: Number,
		default: 0
	},
	duration: {
		type: Number,
		default: 1
	}
});
let numArr = ref(["0", "0", ",", "0", "0", "0", ",", "0", "0", "0"]);
const flipNum = "0123456789";
// let timer = null;
const numberItem = ref<Array<HTMLSpanElement> | null>(null);

// 处理传递过来的数字,转化为数组
function numToArr() {
	const str = props.num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
	numArr.value = str.split("");
}

function rollNum() {
	const numItems = numberItem.value;
	const numberArr = numArr.value.filter(item => item !== "," && item !== ".");
	numberArr.forEach((item, index) => {
		const num = parseInt(item);
		if (numItems) {
			const numItem = numItems[index];
			numItem.style.transform = `translate(-50%, -${num * 10}%)`;
		}
	});
}

// 监听数字变化,更新数字
const initNumber = () => {
	numToArr();
	nextTick(() => {
		setTimeout(() => {
			rollNum();
		}, props.duration * 1000);
	});
};

watch(
	() => props.num,
	() => {
		initNumber();
	}
);

onMounted(() => {
	initNumber();
});
</script>

<style lang="scss" scoped>
.counter-container {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: center;
}
.counter-container .num-item {
	position: relative;
	box-sizing: border-box;
	width: 22px;
	height: 34px;
	padding: 8px;
	margin-left: 4px;
	overflow: hidden;
	font-size: 20px;
	font-weight: bold;
	color: #ffffff;
	text-align: center;
	background-image: url("@/assets/images/dataBoard/num_wrap.png");
	background-repeat: no-repeat;
	background-size: 100% 100%;
}
.counter-container .mark-item {
	height: 34px;
	margin-left: 4px;
	font-size: 24px;
	font-weight: 800;
	line-height: 38px;
	color: #ffffff;
	text-align: center;
}
.counter-container .num {
	position: absolute;
	top: 6px;
	left: 50%;
	letter-spacing: 8px;
	writing-mode: vertical-lr;
	transition: all 1s ease-in-out;
	transform: translate(-50%, 0);
	text-orientation: upright;
}
</style>

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值