用VUE实现数字翻牌效果代码

javascript:

<template>
<div class=”number-flip-container”>
<div
v-for=”(digit, index) in digitCount”
:key=”index”
class=”flip-digit”
>
<div :class=”flipClass(index)” ref=”flipRefs[index]”>
<div class=”digital front” :class=”`number${currentDigits[index]}`”></div>
<div class=”digital back” :class=”`number${nextDigits[index]}`”></div>
</div>
</div>
</div>
</template>

<script>
export default {
name: ‘NumberFlip’,
props: {
// 目标数字
target: {
type: Number,
required: true,
validator: (v) => v >= 0
},
// 数字位数(不足自动补零)
digitCount: {
type: Number,
default: 3
},
// 翻牌间隔时间(ms)
interval: {
type: Number,
default: 100
}
},
data() {
return {
currentDigits: [], // 当前显示的数字数组
nextDigits: [], // 下一个要显示的数字数组
isFlipping: [], // 每个数字的翻转动画状态
timer: null // 滚动定时器
}
},
computed: {
// 格式化目标数字为指定长度的数组
targetDigits() {
const str = this.target.toString().padStart(this.digitCount, ‘0’)
return str.split(”).map(Number)
}
},
mounted() {
// 初始化数字状态
this.initDigits()
// 开始从0翻牌到目标数字
this.startFlipping()
},
beforeDestroy() {
clearInterval(this.timer)
},
methods: {
// 初始化数字数组
initDigits() {
this.currentDigits = Array(this.digitCount).fill(0)
this.nextDigits = Array(this.digitCount).fill(0)
this.isFlipping = Array(this.digitCount).fill(false)
},

// 获取翻牌容器的类名
flipClass(index) {
let base = ‘flip down’
if (this.isFlipping[index]) {
base += ‘ go’
}
return base
},

// 单个数字翻牌
flipDigit(index, newVal) {
if (this.isFlipping[index]) return

this.isFlipping[index] = true
this.nextDigits[index] = newVal

// 动画结束后更新状态
setTimeout(() => {
this.currentDigits[index] = newVal
this.isFlipping[index] = false
}, 600) // 与CSS动画时长保持一致
},

// 检查是否所有数字都已达到目标
checkComplete() {
return this.currentDigits.every((val, i) => val === this.targetDigits[i])
},

// 开始翻牌动画
startFlipping() {
let currentNum = 0
this.timer = setInterval(() => {
if (currentNum >= this.target) {
clearInterval(this.timer)
return
}

currentNum++
// 格式化当前数字为指定长度的数组
const currentStr = currentNum.toString().padStart(this.digitCount, ‘0’)
const currentNumArr = currentStr.split(”).map(Number)

// 逐位对比并触发翻牌
currentNumArr.forEach((val, index) => {
if (val !== this.currentDigits[index]) {
this.flipDigit(index, val)
}
})
}, this.interval)
}
},
watch: {
// 监听目标数字变化,重新开始翻牌
target() {
clearInterval(this.timer)
this.initDigits()
this.startFlipping()
}
}
}
</script>

<style scoped>
.number-flip-container {
display: inline-flex;
gap: 8px; /* 数字之间的间距 */
align-items: center;
}

.flip-digit {
/* 防止翻牌时数字抖动 */
perspective: 200px;
}

/* 翻牌基础样式 */
.flip {
display: inline-block;
position: relative;
width: 60px;
height: 100px;
line-height: 100px;
border: solid 1px #000;
border-radius: 8px;
background: #fff;
font-size: 66px;
color: #fff;
box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
text-align: center;
font-family: “Helvetica Neue”, sans-serif;
}

.digital {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}

/* 数字上下部分拆分(核心技巧) */
.digital:before,
.digital:after {
content: attr(class);
position: absolute;
left: 0;
right: 0;
background: #000;
overflow: hidden;
box-sizing: border-box;
/* 从类名中提取数字(number0 -> 0) */
content: “”;
}

/* 提取数字显示 */
.number0:before, .number0:after { content: “0”; }
.number1:before, .number1:after { content: “1”; }
.number2:before, .number2:after { content: “2”; }
.number3:before, .number3:after { content: “3”; }
.number4:before, .number4:after { content: “4”; }
.number5:before, .number5:after { content: “5”; }
.number6:before, .number6:after { content: “6”; }
.number7:before, .number7:after { content: “7”; }
.number8:before, .number8:after { content: “8”; }
.number9:before, .number9:after { content: “9”; }

/* 上半部分样式 */
.digital:before {
top: 0;
bottom: 50%;
border-radius: 8px 8px 0 0;
border-bottom: solid 1px #666;
}

/* 下半部分样式(line-height:0 实现只显示下半部分文字) */
.digital:after {
top: 50%;
bottom: 0;
border-radius: 0 0 8px 8px;
line-height: 0;
}

/* 翻牌层级与透视设置 */
.flip.down .front:before {
z-index: 3;
}

.flip.down .back:after {
z-index: 2;
transform-origin: 50% 0%; /* 以上边缘为旋转轴 */
transform: perspective(160px) rotateX(180deg);
}

.flip.down .front:after,
.flip.down .back:before {
z-index: 1;
}

/* 翻转动画实现 */
.flip.down.go .front:before {
transform-origin: 50% 100%; /* 以下边缘为旋转轴 */
animation: frontFlipDown 0.6s ease-in-out both;
box-shadow: 0 -2px 6px rgba(255, 255, 255, 0.3);
backface-visibility: hidden; /* 翻转后隐藏背面 */
}

.flip.down.go .back:after {
animation: backFlipDown 0.6s ease-in-out both;
}

/* 向下翻转动画关键帧 */
@keyframes frontFlipDown {
0% { transform: perspective(160px) rotateX(0deg); }
100% { transform: perspective(160px) rotateX(-180deg); }
}

@keyframes backFlipDown {
0% { transform: perspective(160px) rotateX(180deg); }
100% { transform: perspective(160px) rotateX(0deg); }
}
</style>

使用方法如下:

<template>
<div>
<NumberFlip :target=”123″ :digitCount=”3″ />
<NumberFlip :target=”9876″ :digitCount=”5″ :interval=”150″ />
</div>
</template>
<script>
import NumberFlip from ‘./NumberFlip.vue’
export default {
components: { NumberFlip }
}
</script>

关键技术点
数字拆分逻辑:将目标数字转换为指定长度的数组,逐位对比并触发翻牌
动画状态管理:通过isFlipping数组跟踪每个数字的动画状态,避免重复触发
CSS 伪元素技巧:使用before/after拆分数字为上下两部分,配合line-height:0实现下半部分文字显示
3D 透视效果:通过perspective和transform-origin创建立体翻牌视觉效果,backface-visibility避免翻转时显示背面

欢迎使用66资源网
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
7. 本站有不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别!

66源码网 » 用VUE实现数字翻牌效果代码

提供最优质的资源集合

立即查看 了解详情