首先了解两个css
字符排版的样式
writing-mode
设置文本行是水平还是垂直布局
horizontal-tb
:默认值,表示水平排版,从上到下vertical-lr
:表示垂直排版,从左到右vertical-rl
:表示垂直排版,从右到左text-orientation
设定行中字符的方向,仅影响纵向模式(当 writing-mode
的值不是horizontal-tb
)下的文本。此属性在控制使用竖排文字的语言的显示上很有作用,也可以用来构建垂直的表格头
mixed
:默认值,顺时针旋转水平书写的字符 90°,将垂直书写的文字自然布局upright
:将水平书写的字符自然布局(直排),包括垂直书写的文字sideways
:所有字符被布局为与水平方式一样,但是整行文本被顺时针旋转 90°为了效果明显,我们给父元素添加边框作为可视区域,纵向的数字通过transform
在Y轴位移达到滚动效果
<template>
<div class="number">
<span>0123456879span>
div>
template>
<style scoped>
.number {
width: 20px;
height: 20px;
border: 1px solid #333;
}
.number span {
writing-mode: vertical-rl;
text-orientation: upright;
transform: translateY(0%);
}
style>
如下图所示
我们接着把边框去掉,换成overflow: hidden
假如现在有一个6位数字123456,我们想要它从000000滚动到目标数字123456
代码部分:
<template>
<div style="margin-left: 300px;margin-top: 300px;display: flex;align-items: center;">
<div v-for="(item, index) in numberList" :key="index" style="display: flex;">
<div class="number">
<span ref="numberItem" :data-number="item" :data-index="index">0123456879span>
div>
div>
<a-button style="margin-left: 30px;" @click="setNumberTransform">滚动a-button>
div>
template>
<script>
export default {
computed: {
numberList() {
return String(this.value).split("");
}
},
data() {
return {
value: 123456
};
},
methods: {
// 设置每一位数字的偏移
setNumberTransform() {
let numberItems = this.$refs.numberItem;
let obj = {}
Array.from(numberItems).forEach(c => {
let key = c.dataset.index
let value = c.dataset.number
let init = 0
obj[key] = setInterval(() => {
if (init < value * 10) {
init++
c.style.transform = `translateY(-${init}%)`;
} else {
clearInterval(obj[key])
obj[key] = null
}
}, 10); // 控制滚动速率
});
}
},
};
script>
<style scoped lang="less">
.number {
width: 20px;
height: 20px;
border: 1px solid #ccc;
> span {
writing-mode: vertical-rl;
text-orientation: upright;
transform: translateY(0%);
}
}
style>
效果如下:
我们接着把边框去掉,换成overflow: hidden
,效果如下:
创建scroll-number.vue
数字滚动组件
<template>
<div style="display: flex;">
<div v-for="(item, index) in numberList" :key="index" style="display: flex;">
<span v-if="isNaN(item)">{{item}}span>
<div class="number" v-else>
<span
class="number-item"
ref="numberItem"
:data-number="item"
:data-index="index"
>0123456879span>
div>
div>
div>
template>
<script>
export default {
props: {
value: {
type: [String, Number],
default: 0
}
},
watch: {
value(newVal) {
if (newVal) {
this.$nextTick(() => {
this.setNumberTransform();
});
}
}
},
computed: {
numberList() {
return String(this.value).split("");
}
},
data() {
return {};
},
methods: {
// 设置每一位数字的偏移
setNumberTransform() {
let numberItems = this.$refs.numberItem;
let obj = {};
Array.from(numberItems).forEach(c => {
let key = c.dataset.index;
let value = c.dataset.number;
let init = 0;
obj[key] = setInterval(() => {
if (init < value * 10) {
init += 1;
c.style.transform = `translateY(-${init}%)`;
} else {
clearInterval(obj[key]);
obj[key] = null;
}
}, 10);
});
}
},
mounted() {
this.setNumberTransform();
}
};
script>
<style scoped lang="less">
.number {
width: 20px;
height: 20px;
overflow: hidden;
> span {
writing-mode: vertical-rl;
text-orientation: upright;
transform: translateY(0%);
}
}
style>
使用改组件
<scroll-number :value="'412,789,123,41.00'">scroll-number>
效果如下图