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 相关文章推荐
Jquery Ajax学习实例7 Ajax所有过程事件分析示例
Mar 23 Javascript
深入学习AngularJS中数据的双向绑定机制
Mar 04 Javascript
非常酷炫的Bootstrap图片轮播动画
May 27 Javascript
详解PHP中pathinfo()函数导致的安全问题
Jan 05 Javascript
解决微信内置浏览器返回上一页强制刷新问题方法
Feb 05 Javascript
node操作mysql数据库实例详解
Mar 17 Javascript
BootStrap Select清除选中的状态恢复默认状态
Jun 20 Javascript
JavaScript实现鼠标滚轮控制页面图片切换功能示例
Oct 14 Javascript
详细分析JS函数去抖和节流
Dec 05 Javascript
iview的table组件自带的过滤器实现
Jul 12 Javascript
vue实现百度搜索功能
Dec 28 Javascript
element-ui 实现响应式导航栏的示例代码
May 08 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/03/29 PHP
php+ajax实现文章自动保存的方法
2014/12/30 PHP
php中array_multisort对多维数组排序的方法
2020/06/21 PHP
phpcms中的评论样式修改方法
2016/10/21 PHP
php微信公众号开发之简答题
2018/10/20 PHP
PHP如何将图片文件上传到另外一台服务器上
2019/08/26 PHP
常用js脚本
2006/12/03 Javascript
jquery插件之easing使用
2010/08/19 Javascript
Ext JS 4实现带week(星期)的日期选择控件(实战一)
2013/08/21 Javascript
jQuery中wrapAll()方法用法实例
2015/01/16 Javascript
全面解析bootstrap格子布局
2016/05/22 Javascript
JavaScript中的对象继承关系
2016/08/01 Javascript
Bootstrap笔记—折叠实例代码
2017/03/13 Javascript
Vue组件之全局组件与局部组件的使用详解
2017/10/09 Javascript
vue 权限认证token的实现方法
2018/07/17 Javascript
jquery获取元素到屏幕四周可视距离的方法
2018/09/05 jQuery
微信小程序class封装http代码实例
2019/08/24 Javascript
JavaScript实现轮播图片完整代码
2020/03/07 Javascript
axios封装与传参示例详解
2020/10/18 Javascript
[04:04]DOTA2亚洲邀请赛比赛场馆&酒店全攻略
2017/03/23 DOTA
[00:47]TI7不朽珍藏III——沙王不朽展示
2017/07/15 DOTA
Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
2008/09/06 Python
Python时区设置方法与pytz查询时区教程
2013/11/27 Python
pycharm 使用心得(八)如何调用另一文件中的函数
2014/06/06 Python
Flask入门教程实例:搭建一个静态博客
2015/03/27 Python
python中xrange用法分析
2015/04/15 Python
Python中zfill()方法的使用教程
2015/05/20 Python
Python装饰器用法实例分析
2019/01/14 Python
饿了么订餐官网:外卖、网上订餐
2019/06/28 全球购物
一套中级Java程序员笔试题
2015/01/14 面试题
消防安全检查制度
2014/02/04 职场文书
中专自我鉴定
2014/02/05 职场文书
妈妈活动方案
2014/08/15 职场文书
公司领导班子对照材料
2014/08/18 职场文书
离婚协议书范本(2016最新版)
2016/03/18 职场文书