Vue.js实现大屏数字滚动翻转效果


Posted in Javascript onNovember 29, 2019

大屏数字滚动翻转效果来源于最近工作中element后台管理页面一张大屏的UI图,该UI图上有一个模块需要有数字往上翻动的效果,以下是最终实现的效果:

Vue.js实现大屏数字滚动翻转效果

整体思路:

在实现此效果之前,我们先来捋一下思路,用思维导图来设计一下我们的实现步骤,如下:

Vue.js实现大屏数字滚动翻转效果

你可以审查元素,下载数字背景图片,复制图片地址,或者使用其他背景图片、背景颜色

Vue.js实现大屏数字滚动翻转效果

有了以上的设计流程,我们先来简单实现一下:

// CSS代码
<style>
.box-item {
 position: relative;
 display: inline-block;
 width: 54px;
 height: 82px;
 /* 背景图片 */
 background: url(./number-bg.png) no-repeat center center;
 background-size: 100% 100%;
 font-size: 62px;
 line-height: 82px;
 text-align: center;
}
</style>

// htm代码
<div class="box">
 <p class="box-item">
 <span>1</span>
 </p>
</div>

实现以上代码后,它的效果将是下面这样的:

Vue.js实现大屏数字滚动翻转效果

思考:

背景框中有了数字以后,我们现在来思考一下,背景框中的文字,一定是0-9之前的数字,要在不打乱以上html结构的前提下,如何让数字滚动起来呢?这个时候我们的魔爪就伸向了一个CSS属性:writing-mode,下面是它属性的介绍:

  • horizontal-tb:默认值,表示水平排版,从上到下。
  • vertical-lr:表示垂直排版,从左到右。
  • vertical-rl:表示垂直排版,从右到左。

它的实时效果是像下面这样:

Vue.js实现大屏数字滚动翻转效果

根据以上的灵感,我们可以实现下面这样的效果:

Vue.js实现大屏数字滚动翻转效果

代码如下:

// html部分
<p class="box-item">
 <span>0123456789</span>
</p>

// style部分
.box-item {
 display: inline-block;
 width: 54px;
 height: 82px;
 background: url(./number-bg.png) no-repeat center center;
 background-size: 100% 100%;
 font-size: 62px;
 line-height: 82px;
 text-align: center;
 position: relative;
 writing-mode: vertical-lr;
 text-orientation: upright;
 /* overflow: hidden; */
}
.box-item span {
 position: absolute;
 top: 10px;
 left: 50%;
 transform: translateX(-50%);
 letter-spacing: 10px;
}

计算滚动

如果我们想让数字滚动到5,那么滚动的具体到底是多少?

答案是:向下滚动-50%

那么其他的数字呢?

得益于我们特殊的实现方法,每一位数字的滚动距离有一个通用的公式:

transform: `translate(-50%,-${number * 10}%)

有了以上公式,我们让数字滚动到5,它的效果如下:

Vue.js实现大屏数字滚动翻转效果

代码加上 `transform: `translate(-50%,-${number * 10}%)`,示例如下

.box-item span {
 position: absolute;
 top: 10px;
 left: 50%;
 transform: translate(-50%,-50%);
 letter-spacing: 10px;
}

滚动动画的实现

在知道了每一个数字具体的滚动距离后,我们来设计一下,让数字能够随机滚动起来:

Vue.js实现大屏数字滚动翻转效果

一下是让数字随机滚动的JS

setInterval(() => {
 let number = document.getElementById('Number')
 let random = getRandomNumber(0,10)
 number.style.transform = `translate(-50%, -${random * 10}%)`
}, 2000)
function getRandomNumber (min, max) {
 return Math.floor(Math.random() * (max - min + 1) + min)
}

至此,我们数字滚动效果已经初步实现了,在下一节中我们将会逐步完善此效果,以满足业务需求。

完善

在上一节中,我们初步完成了滚动的效果,这一节我们将根据最开始的思维导图来设计一个通用的Vue业务组件

因为我们的业务需要,我们最大的位数是8位数字,所以对不足八位进行补位:

假如传递的位数不足8位,我们需要对它进行补0的操作,补0完成以后,我们也需要把它转换成金额的格式

toOrderNum(num) {
  num = num.toString()
  // 把订单数变成字符串
  if (num.length < 8) {
  num = '0' + num // 如未满八位数,添加"0"补位
  this.toOrderNum(num) // 递归添加"0"补位
  } else if (num.length === 8) {
  // 订单数中加入逗号
  num = num.slice(0, 2) + ',' + num.slice(2, 5) + ',' + num.slice(5, 8)
  this.orderNum = num.split('') // 将其便变成数据,渲染至滚动数组
  } else {
  // 订单总量数字超过八位显示异常
  this.$message.warning('订单总量数字过大,显示异常,请联系客服')
  }
 },

渲染

我们根据上面补位字符串,分隔成字符数组,在页面中进行渲染:

computeNumber:为字符数组,例如:['0','0',',','0','0','0',',','9','1','7']

// html代码
<ul>
 <li
 :class="{'number-item': !isNaN(item) }"
 v-for="(item,index) in computeNumber"
 :key="index"
 >
 <span v-if="!isNaN(item)">
  <i ref="numberItem">0123456789</i>
 </span>
 <span v-else>{{item}}</span>
 </li>
</ul>


// CSS代码
.number-item {
 width: 50px;
 background: url(./number-bg.png) no-repeat center center;
 background-size:100% 100%;
 & > span {
 position: relative;
 display: inline-block;
 margin-right: 10px;
 width: 100%;
 height: 100%;
 writing-mode: vertical-rl;
 text-orientation: upright;
 overflow: hidden;
 & > i {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%,0);
  transition: transform 0.5s ease-in-out;
  letter-spacing: 10px;
 }
 }
}

页面渲染效果:

Vue.js实现大屏数字滚动翻转效果

数字随机增长,模拟轮询效果

页面渲染完毕后,我们来让数字滚动起来,设计如下两个方法,其中increaseNumber需要在Vue生命周期mounted函数中调用

// 定时增长数字
increaseNumber () {
 let self = this
 this.timer = setInterval(() => {
 self.newNumber = self.newNumber + getRandomNumber(1, 100)
 self.setNumberTransform()
 }, 3000)
},
// 设置每一位数字的偏移
setNumberTransform () {
 let numberItems = this.$refs.numberItem
 let numberArr = this.computeNumber.filter(item => !isNaN(item))
 for (let index = 0; index < numberItems.length; index++) {
 let elem = numberItems[index]
 elem.style.transform = `translate(-50%, -${numberArr[index] * 10}%)`
 }
}

最终实现效果:

Vue.js实现大屏数字滚动翻转效果

完整代码如下:

<template>
 <div class="chartNum">
    <h3 class="orderTitle">订单总量</h3>
    <div class="box-item">
     <li :class="{'number-item': !isNaN(item), 'mark-item': isNaN(item) }"
      v-for="(item,index) in orderNum"
      :key="index">
       <span v-if="!isNaN(item)">
        <i ref="numberItem">0123456789</i>
       </span>
      <span class="comma" v-else>{{item}}</span>
     </li>
    </div>
   </div>
</template>
<script>
 export default {
  data() {
   return {
    orderNum: ['0', '0', ',', '0', '0', '0', ',', '0', '0', '0'], // 默认订单总数
   }
  }
  mounted: {
   this.toOrderNum(num) // 这里输入数字即可调用
  },
  methods: {
    // 设置文字滚动
   setNumberTransform () {
    const numberItems = this.$refs.numberItem // 拿到数字的ref,计算元素数量
    const numberArr = this.orderNum.filter(item => !isNaN(item))
    // 结合CSS 对数字字符进行滚动,显示订单数量
    for (let index = 0; index < numberItems.length; index++) {
    const elem = numberItems[index]
    elem.style.transform = `translate(-50%, -${numberArr[index] * 10}%)`
    }
   },
   // 处理总订单数字
   toOrderNum(num) {
    num = num.toString()
    // 把订单数变成字符串
    if (num.length < 8) {
    num = '0' + num // 如未满八位数,添加"0"补位
    this.toOrderNum(num) // 递归添加"0"补位
    } else if (num.length === 8) {
    // 订单数中加入逗号
    num = num.slice(0, 2) + ',' + num.slice(2, 5) + ',' + num.slice(5, 8)
    this.orderNum = num.split('') // 将其便变成数据,渲染至滚动数组
    } else {
    // 订单总量数字超过八位显示异常
    this.$message.warning('订单总量数字过大,显示异常,请联系客服')
    }
   },
  }
 }
</script>
<style scoped lang='scss'>
  /*订单总量滚动数字设置*/
 .box-item {
  position: relative;
  height: 100px;
  font-size: 54px;
  line-height: 41px;
  text-align: center;
  list-style: none;
  color: #2D7CFF;
  writing-mode: vertical-lr;
  text-orientation: upright;
  /*文字禁止编辑*/
  -moz-user-select: none; /*火狐*/
  -webkit-user-select: none; /*webkit浏览器*/
  -ms-user-select: none; /*IE10*/
  -khtml-user-select: none; /*早期浏览器*/
  user-select: none;
  /* overflow: hidden; */
 }
 /* 默认逗号设置 */
 .mark-item {
  width: 10px;
  height: 100px;
  margin-right: 5px;
  line-height: 10px;
  font-size: 48px;
  position: relative;
  & > span {
   position: absolute;
   width: 100%;
   bottom: 0;
   writing-mode: vertical-rl;
   text-orientation: upright;
  }
 }
 /*滚动数字设置*/
 .number-item {
  width: 41px;
  height: 75px;
  background: #ccc;
  list-style: none;
  margin-right: 5px;
  background:rgba(250,250,250,1);
  border-radius:4px;
  border:1px solid rgba(221,221,221,1);
  & > span {
   position: relative;
   display: inline-block;
   margin-right: 10px;
   width: 100%;
   height: 100%;
   writing-mode: vertical-rl;
   text-orientation: upright;
   overflow: hidden;
   & > i {
    font-style: normal;
    position: absolute;
    top: 11px;
    left: 50%;
    transform: translate(-50%,0);
    transition: transform 1s ease-in-out;
    letter-spacing: 10px;
   }
  }
 }
 .number-item:last-child {
  margin-right: 0;
 }
</style>

总结

以上所述是小编给大家介绍的Vue.js实现大屏数字滚动翻转效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
巧妙破除网页右键禁用的十大绝招
Aug 12 Javascript
Javascript操作select方法大全[新增、修改、删除、选中、清空、判断存在等]
Sep 26 Javascript
jQuery下的几个你可能没用过的功能
Aug 29 Javascript
Jquery index()方法 获取相应元素索引值
Oct 12 Javascript
js实现图片轮换效果代码
Apr 16 Javascript
parentElement,srcElement的使用小结
Jan 13 Javascript
JS实现的简洁纵向滑动菜单(滑动门)效果
Oct 19 Javascript
详解JavaScript基本类型和引用类型
Dec 09 Javascript
bootstrap paginator分页前后台用法示例
Jun 17 Javascript
使用vue构建移动应用实战代码
Aug 02 Javascript
vue 内置过滤器的使用总结(附加自定义过滤器)
Dec 11 Javascript
Vue双向数据绑定(MVVM)的原理
Oct 03 Javascript
Vue基础配置讲解
Nov 29 #Javascript
jQuery实现弹幕特效
Nov 29 #jQuery
Vue实现多标签选择器
Nov 28 #Javascript
swiper实现异形轮播效果
Nov 28 #Javascript
Vue请求java服务端并返回数据代码实例
Nov 28 #Javascript
javascript实现异形滚动轮播
Nov 28 #Javascript
javascript实现切割轮播效果
Nov 28 #Javascript
You might like
风格模板初级不完全修改教程
2006/10/09 PHP
PHP正则表达式之定界符和原子介绍
2012/10/05 PHP
phpmyadmin显示utf8_general_ci中文乱码的问题终级篇
2013/04/08 PHP
非集成环境的php运行环境(Apache配置、Mysql)搭建安装图文教程
2016/04/12 PHP
IOS 开发之NSDictionary转换成JSON字符串
2017/08/14 PHP
判断用户的在线状态 onbeforeunload事件
2011/03/05 Javascript
纯JAVASCRIPT图表动画插件Highcharts Examples
2011/04/16 Javascript
使用js判断当前时区TimeZone是否是夏令时
2014/02/23 Javascript
js判断浏览器版本以及浏览器内核的方法
2015/01/20 Javascript
JavaScript ES6中CLASS的使用详解
2016/11/22 Javascript
jQuery实现圣诞节礼物动画案例解析
2016/12/25 Javascript
基于vue开发的在线付费课程应用过程
2018/01/25 Javascript
JSON字符串操作移除空串更改key/value的介绍
2019/01/05 Javascript
命令行批量截图Node脚本示例代码
2019/01/25 Javascript
layui动态渲染生成左侧3级菜单的方法(根据后台返回数据)
2019/09/23 Javascript
详解Vue中的MVVM原理和实现方法
2020/07/15 Javascript
vant时间控件使用方法详解
2020/12/24 Javascript
node.js文件的复制、创建文件夹等相关操作
2021/02/05 Javascript
Python自定义函数定义,参数,调用代码解析
2017/12/27 Python
Python数据分析之双色球统计两个红和蓝球哪组合比例高的方法
2018/02/03 Python
python: line=f.readlines()消除line中\n的方法
2018/03/19 Python
Python实现输出某区间范围内全部素数的方法
2018/05/02 Python
python 列表降维的实例讲解
2018/06/28 Python
python实现布隆过滤器及原理解析
2019/12/08 Python
python实现用户名密码校验
2020/03/18 Python
澳大利亚领先的宠物用品商店:VetSupply
2017/09/08 全球购物
德国珠宝和手表在线商店:VALMANO
2019/03/24 全球购物
美国一站式电动和手动工具商店:International Tool
2020/11/26 全球购物
使用useBean标志初始化BEAN时如何接受初始化参数
2012/02/11 面试题
编程实现当输入某产品代码则打印出该产品记录的功能
2014/05/03 面试题
一道SQL存储过程面试题
2016/10/07 面试题
公务员总结性个人自我评价
2013/12/05 职场文书
法院先进个人事迹材料
2014/05/04 职场文书
十佳标兵事迹材料
2014/08/18 职场文书
高中运动会广播稿
2014/09/16 职场文书
Python中np.random.randint()参数详解及用法实例
2022/09/23 Python