先看效果图

在这里插入图片描述

一、前置条件

首先了解两个css字符排版的样式

1. writing-mode

设置文本行是水平还是垂直布局

  • horizontal-tb:默认值,表示水平排版,从上到下
  • vertical-lr:表示垂直排版,从左到右
  • vertical-rl:表示垂直排版,从右到左
    在这里插入图片描述
    在这里插入图片描述
2. text-orientation

设定行中字符的方向,仅影响纵向模式(当 writing-mode 的值不是horizontal-tb)下的文本。此属性在控制使用竖排文字的语言的显示上很有作用,也可以用来构建垂直的表格头

  • mixed:默认值,顺时针旋转水平书写的字符 90°,将垂直书写的文字自然布局
  • upright:将水平书写的字符自然布局(直排),包括垂直书写的文字
  • sideways:所有字符被布局为与水平方式一样,但是整行文本被顺时针旋转 90°

在这里插入图片描述

二、滚动原理

为了效果明显,我们给父元素添加边框作为可视区域,纵向的数字通过transform在Y轴位移达到滚动效果

    <template>
    	<div class="number">
      		<span>0123456879</span>
	    </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">0123456879</span>
      </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"
        >0123456879</span>
      </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>

效果如下图

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐