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 屏蔽鼠标键盘的几段代码
Jan 02 Javascript
通过JS自动隐藏手机浏览器的地址栏实现原理与代码
Jan 02 Javascript
js实现屏蔽默认快捷键调用自定义事件示例
Jun 18 Javascript
JavaScript基础语法、dom操作树及document对象
Dec 02 Javascript
Jquery的基本对象转换和文档加载用法实例
Feb 25 Javascript
javascript数组去重方法汇总
Apr 23 Javascript
快速处理vue渲染前的显示问题
Mar 05 Javascript
浅谈vue首屏加载优化
Jun 28 Javascript
layui实现table加载的示例代码
Aug 14 Javascript
javascript实现下拉菜单效果
Feb 09 Javascript
Vite + React从零开始搭建一个开源组件库
Jun 25 Javascript
vue本地构建热更新卡顿的问题“75 advanced module optimization”完美解决方案
Aug 05 Vue.js
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
细谈php中SQL注入攻击与XSS攻击
2012/06/10 PHP
PHP中auto_prepend_file与auto_append_file用法实例分析
2014/09/22 PHP
jQuery EasyUI 中文API Button使用实例
2010/04/14 Javascript
关于用Jquery的height()、width()计算动态插入的IMG标签的宽高的问题
2010/12/08 Javascript
最简单的JavaScript验证整数、小数、实数、有效位小数正则表达式
2015/04/17 Javascript
javascript 应用小技巧方法汇总
2015/07/05 Javascript
jQuery采用连缀写法实现的折叠菜单效果
2015/09/18 Javascript
浅谈Javascript中substr和substring的区别
2015/09/30 Javascript
Jquery插件easyUi实现表单验证示例
2015/12/15 Javascript
基于jQuery实现仿百度首页选项卡切换效果
2016/05/29 Javascript
jQuery中的通配符选择器使用总结
2016/05/30 Javascript
javascript之IE版本检测超简单方法
2016/08/20 Javascript
jQuery实现动态添加tr到table的方法
2016/12/26 Javascript
使用prop解决一个checkbox选中后再次选中失效的问题
2017/07/05 Javascript
python爬取安居客二手房网站数据(实例讲解)
2017/10/19 Javascript
windows系统下更新nodejs版本的方案
2017/11/24 NodeJs
JS实现导出Excel的五种方法详解【附源码下载】
2018/03/15 Javascript
js实现聊天对话框
2020/02/08 Javascript
利用vue3+ts实现管理后台(增删改查)
2020/10/30 Javascript
python轻松实现代码编码格式转换
2015/03/26 Python
在RedHat系Linux上部署Python的Celery框架的教程
2015/04/07 Python
实例讲解Python中SocketServer模块处理网络请求的用法
2016/06/28 Python
Python OpenCV实现测量图片物体宽度
2020/05/27 Python
浅谈CSS3中的变形功能-transform功能
2017/12/27 HTML / CSS
HTML5 canvas基本绘图之绘制线条
2016/06/27 HTML / CSS
Java 中访问数据库的步骤?Statement 和PreparedStatement 之间的区别?
2012/06/05 面试题
餐饮主管岗位职责
2013/12/10 职场文书
简历的自我评价范文
2014/02/04 职场文书
火锅店营销方案
2014/02/26 职场文书
大学生自我鉴定书
2014/03/24 职场文书
激励口号大全
2014/06/17 职场文书
团日活动总结怎么写
2014/06/25 职场文书
1000字打架检讨书
2014/11/03 职场文书
焦裕禄纪念馆观后感
2015/06/09 职场文书
JavaScript实现登录窗体
2021/06/22 Javascript
mysql sql常用语句大全
2022/06/21 MySQL