引言
在网页设计中,动画效果往往能给用户带来更加生动和有趣的视觉体验。今天,我们将探讨如何使用CSS动画来实现一个动态数字轮盘滚动效果,这种效果类似于垂直方向的轮播图,可以用于展示计数器、计时器或任何需要动态数字的场景。
原理分析
动态数字轮盘滚动效果的实现基于CSS动画,通过创建一个无限循环的动画来模拟数字的滚动。我们将数字拆分为单个字符,并为每个字符设置不同的延迟时间,以实现数字的连续滚动效果
效果图
实现步骤
1. 父组件
父组件负责接收并传递当前需要显示的数字给子组件AnimateNum
。这里我们使用Vue.js框架,通过v-for
循环渲染每个场景。
<div class="latestSceneFor" v-for="(item, index) in latestSceneList" :key="index">
<div class="latestSceneFor-image">
<img :src="item.url" />
</div>
<div class="latestSceneFor-title">
<div class="name">{{ item.name }}</div>
<AnimateNum class="value" :curNum="item.value" :size="50"/> //引用组件
</div>
</div>
import AnimateNum from '../components/AnimateNum.vue'
components: {
AnimateNum,
},
data() {
return {
latestSceneList: [
{
url: require('../assets/images2/basicImg1.png'),
name: '告警总数',
value: '121',
},
{
url: require('../assets/images2/basicImg2.png'),
name: '告警生成事件总数',
value: '96',
},
{
url: require('../assets/images2/basicImg4.png'),
name: '告警未处理数',
value: '30',
},
{
url: require('../assets/images2/basicImg5.png'),
name: '告警事件超时数',
value: '12',
},
],
}
},
<style lang="scss" scoped>
.latestSceneFor {
width: 50%;
display: flex;
align-items: center;
.latestSceneFor-image {
display: flex;
align-items: center;
width: 115px;
height: 116px;
padding-right: 25px;
img {
width: 110px;
height: 100px;
}
}
.latestSceneFor-title {
display: flex;
flex-direction: column;
justify-content: space-around;
flex: 1;
height: 116px;
.name {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 28px;
color: #ffffff;
}
.value {
font-family: tfont;
font-size: 46px;
line-height: 0;
text-shadow: 0px 1 12 rgba(32, 95, 244, 0.97);
::v-deep .scroll-num {
color: #99eeff;
}
}
}
}
</style>
2. AnimateNum组件
AnimateNum
组件接收父组件传递的数字,并将其拆分为单个数字,然后为每个数字创建一个AnimateNumItem
实例。每个实例都有其自己的延迟时间,以便它们可以依次停止滚动。
<template>
<div class="number-box">
<AnimateNumItem
v-for="(item, index) in scrollNumber"
:key="'numItem' + index + Date.now()"
:num="Number(item.num)"
:delay="item.delay"
:size="item.size"
/>
</div>
</template>
<script>
import AnimateNumItem from './AnimateNumItem.vue'
export default {
name: 'AnimateNum',
components: {
AnimateNumItem
},
props: {
// 自定义尺寸
size: { type: Number, default: 33 },
curNum: {
type: [String, Number],
default: 0,
},
},
data: () => ({
showAnimate: true, // 控制无限滚动结束
}),
computed: {
scrollNumber() {
const numberList = String(this.curNum).split('')
const list = []
numberList.map((item, index) => {
list.push({
'num': item, // 定位的数字 CSS变量,提供到style使用
'delay': numberList.length - index, // 每个数字延迟停止
'size': this.size+'px',
})
})
return list
},
},
}
</script>
<style lang="scss" scoped>
.number-box {
display: flex;
flex-direction: row;
align-items: center;
}
</style>
3. AnimateNumItem组件
AnimateNumItem
组件是实现单个数字滚动的核心,负责实现单个数字的滚动动画。它接收num
、delay
和size
三个属性,并使用CSS动画来实现数字的滚动效果。动画效果由@keyframes
定义,并通过.animate
类应用到滚动数字列表上。
<template>
<div class="scroll-box" :style="scrollStyle" @animationend="showAnimate = false">
<!-- 使用v-for循环渲染0到9的数字,以供滚动效果使用 -->
<ul ref="num" class="scroll-num" :class="{ animate: showAnimate }">
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>0</li>
</ul>
</div>
</template>
<script>
export default {
name: 'AnimateNumItem',
props: {
// 定位的数字
num: {
type: Number,
default: 0,
validator: n => n < 10 && n >= 0 && Number.isInteger(n),
},
// 动画延迟时间,控制数字滚动的先后顺序
delay: { type: Number, default: 1 },
// 自定义尺寸
size: { type: String, default: '' },
},
data: () => ({
showAnimate: true, // 控制无限滚动结束
}),
computed: {
scrollStyle() {
return {
// 返回一个对象,包含CSS变量,这些变量将在模板中使用
'--num': this.num,
'--delay': this.delay,
'--width': this.size,
}
},
},
}
</script>
<style lang="scss" scoped>
/* 定义滚动动画的关键帧 */
@keyframes move {
0% {
transform: translateY(-90%);
filter: blur(2px);
}
100% {
transform: translateY(1%);
filter: blur(2px);
}
}
@keyframes num-bounce {
/* 根据当前数字num的值,计算初始偏移量 */
0% {
transform: translateY(calc(var(--num) * -9.09% - 7%));
filter: none; /* 最后取消模糊效果 */
}
25% {
transform: translateY(calc(var(--num) * -9.09% + 3%));
}
50% {
transform: translateY(calc(var(--num) * -9.09% - 1%));
}
70% {
transform: translateY(calc(var(--num) * -9.09% + 0.6%));
}
85% {
transform: translateY(calc(var(--num) * -9.09% - 0.3%));
}
100% {
transform: translateY(calc(var(--num) * -9.09%));
filter: none; /* 最后取消模糊效果 */
}
}
.scroll-box {
width: var(--width, 20px);
height: calc(var(--width, 20px) * 1.8);
color: #fff;
font-size: calc(var(--width, 20px) * 1.1);
line-height: calc(var(--width, 20px) * 1.8);
text-align: center;
overflow: hidden;
flex-shrink: 0; /* 保证不被压缩 */
}
/* 当动画类被激活时应用的样式 */
.animate {
animation: move 1s linear infinite, num-bounce 1s calc(var(--delay) * 1s) forwards;
/* forwards:停在动画的最后一帧 */
}
.scroll-num {
padding: 0;
margin: 0;
list-style: none;
transform: translateY(calc(var(--num) * -9.09%));
}
</style>
在AnimateNumItem
组件的样式中,我们定义了两个关键帧动画:move
和num-bounce
。
move
动画用于创建无限循环的垂直滚动效果。num-bounce
动画用于控制数字的滚动和停止,以及设置延迟时间。
结语
通过上述步骤,我们实现了一个数字轮盘滚动的CSS动画效果。这种方法不仅能够提升网页的视觉效果,还能够吸引用户的注意力。希望这篇技术博客能够帮助你在自己的项目中实现类似的动画效果。