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 相关文章推荐
javascript 传统事件模型构造的事件监听器实现代码
May 31 Javascript
IE图片缓存document.execCommand(&quot;BackgroundImageCache&quot;,false,true)
Mar 01 Javascript
JavaScript面向对象程序设计三 原型模式(上)
Dec 21 Javascript
javascript window.open打开新窗口后无法再次打开该窗口问题的解决方法
Apr 12 Javascript
jquery动态添加删除(tr/td)
Feb 09 Javascript
JavaScript重载函数实例剖析
May 13 Javascript
node网页分段渲染详解
Sep 05 Javascript
jQuery实现页面倒计时并刷新效果
Mar 13 Javascript
package.json文件配置详解
Jun 15 Javascript
node.js将MongoDB数据同步到MySQL的步骤
Dec 10 Javascript
小程序实现多列选择器
Feb 15 Javascript
微信小程序 image组件遇到的问题
May 28 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
打造计数器DIY三步曲(下)
2006/10/09 PHP
PHP url的pathinfo模式加载不同控制器的简单实现
2016/08/12 PHP
Jquery异步请求数据实例代码
2011/12/28 Javascript
深入理解javascript中defer的作用
2013/12/11 Javascript
基于jQuery的图片不完全按比例自动缩小
2014/07/11 Javascript
js控制页面的全屏展示和退出全屏显示的方法
2015/03/10 Javascript
jQuery实现带有上下控制按钮的简单多行滚屏效果代码
2015/09/04 Javascript
jQuery实现带有动画效果的回到顶部和底部代码
2015/11/04 Javascript
使用angularjs创建简单表格
2016/01/21 Javascript
js自定义select下拉框美化特效
2016/05/12 Javascript
Angularjs渲染的 using 指令的星级评分系统示例
2017/11/09 Javascript
vue-cli3脚手架的配置及使用教程
2018/08/28 Javascript
angular4笔记系列之内置指令小结
2018/11/09 Javascript
JavaScript解析JSON数据示例
2019/07/16 Javascript
解决layer 动态加载select 失效的问题
2019/09/18 Javascript
bootstrap-table后端分页功能完整实例
2020/06/01 Javascript
使用Vue-cli 中为单独页面设置背景图片铺满全屏
2020/07/17 Javascript
[00:32]2018DOTA2亚洲邀请赛EG出场
2018/04/03 DOTA
Python isinstance判断对象类型
2008/09/06 Python
python引入导入自定义模块和外部文件的实例
2017/07/24 Python
python实现在IDLE中输入多行的方法
2018/04/19 Python
Python socket非阻塞模块应用示例
2019/09/12 Python
解决json中ensure_ascii=False的问题
2020/04/03 Python
Pycharm修改python路径过程图解
2020/05/22 Python
详解python安装matplotlib库三种失败情况
2020/07/28 Python
学生如何注册Pycharm专业版以及pycharm的安装
2020/09/24 Python
详解Python Celery和RabbitMQ实战教程
2021/01/20 Python
Penhaligon’s英国官网:成立于1870年的英国香水制造商
2021/02/18 全球购物
八皇后问题,输出了所有情况,不过有些结果只是旋转了90度
2016/08/15 面试题
95%的面试官都会问到的50道Java线程题,附答案
2012/08/03 面试题
私人会所最新创业计划书范文
2014/03/24 职场文书
请假条范文大全
2014/04/10 职场文书
住宿生擅自离校检讨书
2014/09/22 职场文书
高三英语复习计划
2015/01/19 职场文书
2015年学生会干事工作总结
2015/04/09 职场文书
互联网的下一个风口:新的独角兽将诞生
2019/08/02 职场文书