Vue 数据滚动效果实现
0123456789
0123456789
上面动画效果的实现最重要的步骤是要去每次改变 0-9 的数字,然后通过 CSS3 的动画来实现滚动效果。
实现数字布局
实现布局非常的简单
0123456789css
.amount-wrapper1 {
display: inline-block;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
background-color: #42b883;
border-radius: 5px;
}
.amount-wrapper1 em {
display: block;
}
.amount-wrapper1 em i {
display: block;
width: 100%;
height: 100%;
text-align: center;
line-height: 60px;
font-size: 32px;
font-weight: bold;
color: red;
}
可以看到布局的 css 非常简单,主要是限制父级元素的宽度和高度,然后通过子块级元素的特性自动向下堆叠,就可以将数字排列起来了。
让数字动
让数字动起来,这里是用到的 css3 中得 transform
属性,通过 translateY
来实现向下移动的效果。然后在 transition
中设置动画的时间和动画的效果,就可以实现数字的滚动效果了,于此同时将最外层的元素设置为 overflow: hidden
,这样就可以在通过数字变动的时候动态设置 transform
的值,从而实现滚动效果。
css
0123456789.amount-wrapper2 em {
display: block;
transform: translateY(-10%);
transition: transform 0.5s ease-in-out;
}
css
.amount-wrapper2 {
display: inline-block;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
background-color: #42b883;
border-radius: 5px;
overflow: hidden;
}
.amount-wrapper2 em {
display: block;
transform: translateY(-10%);
transition: transform 0.5s ease-in-out;
}
.amount-wrapper2 em i {
display: block;
width: 100%;
height: 100%;
text-align: center;
line-height: 60px;
font-size: 32px;
font-weight: bold;
color: red;
}
计算滚动
在上述代码中可以看到页面展示 1 时,只需要将 em
元素向上移动 10% 的高度就可以了,那么当数字变成 2 的时候,就需要将 em
元素向下移动 20% 的高度,以此类推,当数字变成 9 的时候,就需要将 em
元素向下移动 90% 的高度,这样就可以实现滚动的效果了。
以此类推 em
的 transform
的值就是 translateY(-10% * num)
,这里的 num
就是数字的值,那么当数字变化的时候,就需要动态的改变 em
的 transform
的值。
所以可以在数字变化的时候,动态的改变 em
的 transform
的值,从而实现滚动的效果。
实现滚动
页面需要展示数字的千分位,所以需要将数字转换成数组,然后通过 v-for
来展示每一位数字,这样就可以实现千分位的展示了。
js
// 数字转千分位数组
amountArr() {
return this.amount.toString().replace(/(\d)(?=(\d{3})+$)/g, "$1,").split('')
}
接下来是随机增长数字,这里是通过 setInterval
来实现模拟接口效果
js
setInterval(() => {
this.increaseRandom()
// increaseInterval 为随机增长的时间间隔
}, this.increaseInterval)
increaseRandom() {
const random = Math.floor(Math.random() * 100) + 1
this.amount += random
// 重新设置位置
this.setAmoundPosition()
}
setAmoundPosition() {
// amount 为每个数字的 DOM 元素
const amount = this.$refs.amount
// amountNumber 为纯数字转换成数组
const amountNumber = this.amount.toString().split('')
amount.forEach((el, index) => {
// 获取当前位数的数字
const number = amountNumber[index]
// 获取当前位数的 em 元素
const em = el.querySelector('em')
// 设置 em 元素的 transform 的值
em.style.transform = `translateY(-${number * 10}%)`
})
}
通过上述代码就可以实现数字的滚动效果了。
点击查看完整代码
vue
<template>
<div class="amount-number">
<div class="amount-number__item" v-for="(n, index) in amountArr" :key="index">
<span v-if="!isNaN(n)" class="amount-number__item-number" ref="amount">
<em :style="{transition: `transform ${transitionDuration}s ease-in-out`}">
<i>0</i>
<i>1</i>
<i>2</i>
<i>3</i>
<i>4</i>
<i>5</i>
<i>6</i>
<i>7</i>
<i>8</i>
<i>9</i>
</em>
</span>
<span v-else class="amount-number__item-comma">{{ n }}</span>
</div>
</div>
</template>
<script>
export default {
props: {
num: {
type: Number,
default: 0
},
increaseInterval: {
type: Number,
default: 5000
},
transitionDuration: {
type: Number,
default: 0.5
}
},
data() {
return {
amount: this.num
}
},
mounted() {
this.$nextTick(() => {
this.setAmoundPosition()
})
setInterval(() => {
this.increaseRandom()
}, this.increaseInterval)
},
computed: {
// 数字转数组
amountArr() {
return this.amount.toString().replace(/(\d)(?=(\d{3})+$)/g, "$1,").split('')
}
},
methods: {
// 随机增长 1-100
increaseRandom() {
const random = Math.floor(Math.random() * 100) + 1
this.amount += random
// 重新设置位置
this.setAmoundPosition()
},
// 设置数字位置
setAmoundPosition() {
const amount = this.$refs.amount
const amountNumber = this.amount.toString().split('')
amount.forEach((el, index) => {
const number = amountNumber[index]
const em = el.querySelector('em')
em.style.transform = `translateY(-${number * 10}%)`
})
}
}
}
</script>
<style scoped>
/* .amount {
width: 100%;
color: #fff;
} */
.amount-number {
display: flex;
justify-content: center;
column-gap: 10px;
width: 100%;
}
.amount-number__item {
font-size:36px;
font-weight: bold;
color: #fff;
}
.amount-number__item-number {
display: inline-block;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
background-color: #42b883;
border-radius: 5px;
overflow: hidden;
}
.amount-number__item-number em {
display: block;
transform: translateY(-10%);
}
.amount-number__item-number i {
display: block;
width: 100%;
height: 100%;
text-align: center;
line-height: 60px;
}
.amount-number__item-comma {
display: flex;
flex-direction: column;
justify-content: end;
height: 60px;
color: #42b883;
}
</style>