likes
comments
collection
share

基于iconfont实现BI大屏的CountUp组件

作者站长头像
站长
· 阅读数 20

素材准备

  • iconfont内数字Icon 十个

基于iconfont实现BI大屏的CountUp组件

实现原理

注意看下面灵魂画手的示意图,整个countUp容器,从左到右排列着每个数字容器,设置超出部分隐藏,然后每个数字容器从上到下排列好每一个数字,从0到9,从0到9我们可以想到什么? 我们注意到,数字一共10个, 整个容器高度100%,如果我们根据当前位置所在的数字,进行对应的平移操作,再加上transition过渡效果,不就可以实现countUp效果了吗?

基于iconfont实现BI大屏的CountUp组件

具体实现

  • 页面结构

基于iconfont实现BI大屏的CountUp组件

  • 字符输入控件 提供一个输入控件,可以自定义想要自增的数值
 <input
    type="number"
    onKeypress="return (/[\d]/.test(String.fromCharCode(event.keyCode)))"}"
    oninput="if(value.length>10)value=value.slice(0,10)"
    id="text"
  >

添加change事件,更新我们要展示的number,至于事件里做了什么,我们下面再说

 $('#text').change(function () {
    number = $(this).val()
    countUpAnimate(color)
    if (t) {
      clearInterval(t)
      t =  setInterval(function () {
        number++
        countUpAnimate(color)
      }, 1500)
    }
  })

基于iconfont实现BI大屏的CountUp组件

  • 颜色选择控件 提供一个颜色选择控件,可以自定义想要展示的颜色
<input id="color" type="color">

添加change事件,更新我们要展示的颜色,至于事件里做了什么,我们同样下面再说

 $('#color').change(function () {
    color = $(this).val()
    countUpAnimate(color)
    if (t) {
      clearInterval(t)
      t =  setInterval(function () {
        number++
        countUpAnimate(color)
      }, 1500)
    }
  })
  • 根据上面提供的结构,构造初始化的数组容器
 <div id="countup">

  </div>
  // 容器
  #countup {
    width: 50vw;
    height: 60px;
    border-radius: 8px;
    color: #20777a;
    padding: 5px;
    display: flex;
    justify-content: space-around;
    align-items: center;
    position: absolute;
    top: 350px;
    left: 0;
    right: 0;
    margin: auto;
  }
  /*滚动数字设置*/
  每个数字容器
  .number-item {
    width: 100%;
    height: 100%;
    overflow: hidden;
  }

  .number-item>div {
    transition: transform 1s ease-in-out;
  }
  .number-item>div>div{
    height: 60px;
    line-height: 60px;
    font-size: 30px;
    text-align: center;
  }
  
// 存放所有数字的容器
let numberStr = `
    <div class="box">
      <div class="iconfont icon-shuzi0 fs30"></div>
      <div class="iconfont icon-shuzi1 fs30"></div>
      <div class="iconfont icon-shuzi2 fs30"></div>
      <div class="iconfont icon-shuzi3 fs30"></div>
      <div class="iconfont icon-shuzi4 fs30"></div>
      <div class="iconfont icon-shuzi5 fs30"></div>
      <div class="iconfont icon-shuzi6 fs30"></div>
      <div class="iconfont icon-shuzi7 fs30"></div>
      <div class="iconfont icon-shuzi8 fs30"></div>
      <div class="iconfont icon-shuzi9 fs30"></div>
    </div>
  `
  // 初始化的数字集
let arr = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
// 动态创建dom
  arr.map(v => {
    let div = $('<div>')
    div.addClass('number-item')
    div.html(numberStr)
    $('#countup').append(div)
  })

基于iconfont实现BI大屏的CountUp组件

  • 对获取到的数字进行补位,补足10位
function countUpAnimate() {
    //  总长为10个数字,不足十个数字的长度
    toAmountNum(number)
  }
  // 处理数字
  function toAmountNum(num) {
    num = num.toString()
    let data
    // 把数字转为字符串变成字符串,补零
    if (num.length < 10) {
      num = '0' + num // 如未满十位数,添加"0"补位
      toAmountNum(num) // 递归添加"0"补位
    } else if (num.length === 10) {
      data = num.split('') // 将其便变成数据,渲染至滚动数组
      // 渲染的方法
      setNumberTransform(data)
    } else {
      num = num.slice(0, 10) //超过10位的直接截取
      number = num
      data = num.split('') // 将其便变成数据,渲染至滚动数组
      setNumberTransform(data)
    }
  }
  • 根据数字设置平移的大小,实现动画 只需要设置平移Y轴对应的百分比,就能准确显示对应的数字
// 设置文字滚动
  function setNumberTransform(data) {
     // 每个数字容器
    let children = $('#countup .box')
    let len = 10 - number.toString().length

    for (let i = 0; i < 10; i++) {
      $(children[i]).css('color', color)
    }
    for (let i = 0; i < len; i++) {
      $(children[i]).css('color', '#20777a')
    }
    // 结合CSS 对数字字符进行滚动,显示数量,
    for (let index = 0; index < children.length; index++) {
      const elem = children[index]
      elem.style.transform = `translate(0, -${data[index] * 10}%)`
    }
  }
  • 模拟数据自增,实现动画
countUpAnimate(color)
  let t =  setInterval(function () {
   number++
    countUpAnimate(color)
  }, 1500)

这个动画就是经典的数学与css的结合,我们只需要建立属性-数字间的这种关联关系,就不难写出优秀的动画