原生JS手写animate函数

1 animate动画需求说明

 1.1 animate函数,参数设定

  •  params {dom} 要运动的元素
  •  params {attr} 要运动的属性
  •  params {target} 运动的目标位置
  •  params {callback} 运动完成后的回调函数,可选

1.2 功能说明

  1.  支持任意带px单位的属性运动,如 left top width marginLeft fontSize ...
  2.  支持opacity的属性运动,范围0-100
  3.  支持scrollLeft和scrollTop的属性运动
  4. 支持一个元素依次执行多个运动
  5.  支持一个元素同时执行多个属性的运动

1.3 要运动的属性的三个关键点

  1.    属性名
  2.    属性初始值
  3.    属性目标值

2 手写animate函数-示例代码

function animate(options) {
 

  // 遍历options.attrs对象
  for (var attr in options.attrs) {
    // attr -> 'left'  'top'

    // 获取el元素初始的值和目标值
    if (attr === 'opacity') {
      var current = getComputedStyle(options.el)[attr] * 100 // 1 * 100
    } else if (attr === 'scrollLeft' || attr === 'scrollTop') {
      var current = options.el[attr]
    } else {
      var current = parseInt(getComputedStyle(options.el)[attr]) // '588px' -> 588
    }
    var target = options.attrs[attr]

    // 修改options.attrs的数据结构
    options.attrs[attr] = {
      current: current,
      target: target,
    }
  }
  // console.log( options.attrs );

  // 先清除再启动计时器
  clearInterval(options.el.timer)
  options.el.timer = setInterval(function () {
    for (var attr in options.attrs) {
      // attr -> 'left'  'top'

      // 计算生成一个不断变化的速度
      var speed =
        (options.attrs[attr].target - options.attrs[attr].current) / 10 // 58.8  52.7  45.5  37.3 ...
      // 浏览器识别最小是1px,所以需要对speed取整
      // 速度不能为0,到达不了目标位置
      // speed为正数时,向上取整,保证速度最小为1
      // speed为负数时,向下取整,保证速度最小为1
      speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed)

      // 当前位置累加速度
      options.attrs[attr].current += speed

      // 判断运动停止条件:剩余运动量 <= 每次的运动量
      if (
        Math.abs(options.attrs[attr].target - options.attrs[attr].current) <=
        Math.abs(speed)
      ) {
        // 到达目标位置
        if (attr === 'opacity') {
          options.el.style[attr] = options.attrs[attr].target / 100
        } else if (attr === 'scrollLeft' || attr === 'scrollTop') {
          options.el[attr] = options.attrs[attr].target
        } else {
          options.el.style[attr] = options.attrs[attr].target + 'px'
        }
        // 删除options.attrs对象中运动完成的属性
        delete options.attrs[attr]

        for (var key in options.attrs) {
          // 对象有属性才会执行这里
          return // 结束执行当前函数
        }

        // 清除计时器
        clearInterval(options.el.timer)
        //console.log('到达目标位置。。。')

        // 运动完成后执行回调函数
        typeof options.cb === 'function' && options.cb()
      } else {
        // 修改box的位置
        if (attr === 'opacity') {
          options.el.style[attr] = options.attrs[attr].current / 100
        } else if (attr === 'scrollLeft' || attr === 'scrollTop') {
          options.el[attr] = options.attrs[attr].current
        } else {
          options.el.style[attr] = options.attrs[attr].current + 'px'
        }
      }
    }
  }, 20)
}

2.1 animate函数-参数说明示例代码:


options = {
      el: box,
      cb: function (){
          box.style.backgroundColor = 'green';
      },
      attrs: {
          left: 1100,
          top: 500
      }
  }

2.2 animate函数-函数使用示例代码:

实现文字轮播效果:

        /*
        文字轮播:
        1,copy第一行文字放到最末尾
        2,控制定位:top的值(负值),让文字向上走。
        3,走到最后一行时,瞬间拉回到top:0
    */
    
    // true,深拷贝
    var tmp = ul.children[0].cloneNode(true);
    ul.appendChild(tmp);
    // console.log(tmp);
    autoPlay();
    function autoPlay(){
        var index = 0;
        setInterval(function(){
            index++;
            // ul.style.top = -index * ul.children[0].clientHeight;

            animate({
                el: ul,
                attrs: {
                    // target
                    top: -index * ul.children[0].clientHeight
                },
                cb:function(){
                    if(index === ul.children.length -1){
                        // 初始化为最初状态
                        index = 0;
                        ul.style.top = 0;
                    }
                }
            });
        },1000);
    }

html布局-示例代码:

  • 满 ¥99 顺丰包邮1
  • 满 ¥99 顺丰包邮1

你可能感兴趣的:(前端,javascript,animate动画)