JS实现排行动画

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>排行动画</title>
  <style>
    html, body, div, ul, li, img, span {
      padding: 0;
      margin: 0;
    }

    ul, li {
      list-style: none
    }

    span {
      display: inline-block;
    }

    img {
      vertical-align: top;
    }

    #box {
      padding: 20px;
      height: 700px;
    }

    #box ul {
      padding-left: 20px;
      position: relative;
    }

    #box li {
      margin-left: 60px;
      height: 28px;
      box-sizing: border-box;
      position: absolute;
      line-height: 28px;
      transition: width ease 1s, transform ease 1s, opacity ease 1s;
      opacity: 0;
      background: #ddd;
      border-radius: 20px;
      box-shadow: inset -5px 0px 25px rgba(0,0,0,.4);
    }

    #box li .name {
      position: absolute;
      left: -60px;
      white-space: nowrap;
    }

    #box li .count {
      margin-left: 15px;
      position: absolute;
      left: 100%;
      font-size: 18px;
      letter-spacing: 1px;
      color: #fff;
      font-style: italic;
      text-shadow: 1px 0 2px #000, 0 1px 2px #000;
    }
  </style>
</head>
<body>
<div id="box">
  <h3>销量排行</h3>
  <ul id="list"></ul>
</div>
<script>
  class Animate {
    constructor () {
      this._baseData;
      this.htmlDOMData = [];
    }

    init() {
      // 初始化数据
      this._initArr();

      // 创建动画
      this._createAnimate();

      // 新增事件
      this._addNewAnimate();
    }

    _initArr() {
      let data = [];

      for(let i = 0; i < 10; i++) {
        let _obj = {
          id: `id${i+1}`,
          name: `第${i+1}位`,
          count: parseInt(Math.random()*800)
        };
        data.push(_obj)
      }
      this._baseData = data;
    }

    _createAnimate() {
      // 如果是第一次先创建DOM元素,不是就开始动画
      for(let i = 0; i < 5; i++) {
        if(i === 0) {
          this._firstCreate();
        } else {
          setInterval(() => {
            this._beginAnimate()
          }, i * 3000)
        }
      }
    }

    _firstCreate() {
      this._first = false;
      let bar = document.querySelector('#list');

      this._baseData.sort((l, n) => n.count - l.count);
      this._baseData.forEach((_data, index) => {
        let li = this._createLiDom(_data, index);
        bar.appendChild(li);

        this.htmlDOMData.push({
          id: _data.id,
          el: li
        })
      })
    }

    // 随机生成bar背景颜色
    _createBgColor() {
      return `rgb(${parseInt(Math.random()*255)}, ${parseInt(Math.random()*255)}, ${parseInt(Math.random()*255)})`
    }

    // 创建单个bar元素
    _createLiDom(data, index) {
      let li = document.createElement('li');
      let name = document.createElement('span');
      let count = document.createElement('span');

      name.classList.add('name');
      name.innerText = data.name;

      count.classList.add('count');
      count.innerText = data.count;

      li.style.opacity = 1;
      li.style.width = `${data.count}px`;
      li.style.background = this._createBgColor();
      li.style.transform = `translateY(${index*40}px)`;

      li.append(name, count);
      return li;
    }

    // 开始动画的函数
    _beginAnimate() {
      let bar = document.querySelector('#list');
      let newData = this._reoederBasedata(); // 重排数据

      newData.forEach((_l, i) => {
        this.htmlDOMData.some((n, k) => {
          if(_l.id === n.id) {
            n.el.style.width = `${_l.count}px`;
            n.el.style.transform = `translateY(${i*40}px)`;
            n.el.lastElementChild.innerText = _l.count;
          }

          if(n.isNew) {
            bar.appendChild(n.el)
            n.isNew = false;
          }
        })
      })
    }

    // 重新排序
    _reoederBasedata() {
      this._baseData.forEach(_d => {
        _d.count = parseInt(Math.random()*800);
      })

      return this._baseData.sort((l, n) => n.count - l.count);
    }

    // 添加新数据的动画
    _addNewAnimate() {
      let num = 0, timer = null;

      timer = setInterval(() => {
        num += 1;
        this._addNewData()

        if(num > 3) { // 新增到4个之后就清除定时器
          num = 0;
          clearInterval(timer);
        }
      }, 6000);
    }

    // 添加新数据
    _addNewData() {
      let len = this._baseData.length;
      let _new = {
        id: `id${len+1}`,
        name: `第${len+1}位`,
        count:  parseInt(Math.random() * 800)
      }
      let li = this._createLiDom(_new, len+1);

      this._baseData.push(_new);
      this.htmlDOMData.push({
        id: `id${len+1}`,
        el: li,
        isNew: true
      })
    }
  }

  let myAnimate = new Animate();
  myAnimate.init()
</script>
</body>
</html>

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值