感谢原文作者分享! 点击传送~ 你可能需要这样的大屏数字滚动效果 - 掘金 (juejin.cn)
再次感谢原文作者的分享,本文为在原文代码上进行完善封装的一个翻牌子组件
具体的实现思路原文说的很清晰,这里就不再赘述,想了解的小伙伴可以查看原文
框架:Vue3
源码
创建公共组件 FlipCardNumber.vue
<template>
<div id="flip_card_number">
<ul class="ul_dom">
<li :class="{ 'number-item': !isNaN(item) }" v-for="(item, index) in state.computeNumber" :key="index">
<span v-if="!isNaN(item)">
<i :class="'numberItem' + props.selfClassId">0123456789</i>
</span>
<p v-else class="not_num_span">{{ item }}</p>
</li>
</ul>
</div>
</template>
<script setup>
import {
watch,
nextTick,
onBeforeMount,
onBeforeUnmount,
onMounted,
reactive,
ref,
} from "vue";
const props = defineProps({
statisticalVal: { // 按钮name
type: [String, Number],
// default: '00000'
},
selfClassId: { // 翻牌子组件循环id标识
type: [String, Number],
default: 0
},
})
const state = reactive({
classNum: '', // 为了区分不同组件的翻牌子
newNumber: 0, // 获取到的新数字
computeNumber: ['0', '0', ',', '0', '0', '0', ',', '0', '0', '0'], // 页面展示循环滚动的数字数组
})
watch(
() => props.statisticalVal,
(val, preVal) => {
// console.log(val, preVal, 'val, preValval, preVal');
state.classNum = props.selfClassId
increaseNumber(val)
},
);
onMounted(() => {
})
const increaseNumber = (val) => {
let difference = 0
if (val > state.newNumber) {
difference = val - state.newNumber
} else if (val < state.newNumber) {
difference = state.newNumber - val
}
state.newNumber = state.newNumber + (difference)
let comN = state.newNumber.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
state.computeNumber = comN.split('');
setNumberTransform()
}
const setNumberTransform = () => {
let numberItems = document.getElementsByClassName('numberItem' + state.classNum)
let numberArr = state.computeNumber.filter(item => !isNaN(item))
for (let index = 0; index < numberItems.length; index++) {
let elem = numberItems[index]
elem.style.transform = `translate(-50%, -${numberArr[index] * 10}%)`
}
}
</script>
<style scoped lang="less">
#flip_card_number {
height: 4rem;
}
.ul_dom {
height: 100%;
margin: 0 auto;
padding: 0;
font-size: 3rem;
display: flex;
justify-content: center;
list-style-type: none;
}
.number-item {
width: 2rem;
background-size: 100% 100%;
span {
position: relative;
display: inline-block;
margin-right: 10px;
width: 100%;
height: 100%;
writing-mode: vertical-rl;
text-orientation: upright;
overflow: hidden;
i {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, 0);
transition: transform 0.5s ease-in-out;
letter-spacing: 10px;
}
}
}
.not_num_span {
margin: 0;
line-height: 50px;
}
</style>
其中父组件传输的selfClassId是一个页面中展示多个翻牌组件需要的,如果页面中只有一个组件,可不传
父组件使用
// 1、引入
<script setup>
import FlipCardNumber from "@/components/FlipCardNumber.vue"
</script>
// 2、使用
<template>
<div>
<FlipCardNumber :statisticalVal="valCount" :selfClassId="0"/>
</div>
</template>
valCount是从接口获取到的最新数字
再次说明 selfClassId 在一个页面中使用多个 <FlipCardNumber> 时需要添加的,如果页面中只有一个 <FlipCardNumber> 无需添加