动画函数封装

108 阅读2分钟

利用javascript延时器封装两个通用的运动函数:匀速动画和缓动动画 utils/animate.js

;(function () {
  /**
     * 匀速动画
     * @param {*} ele 执行动画元素
     * @param {*} obj 该元素的哪些属性需要执行动画
     * @param {*} fn  动画执行完成后可能还需要执行的操作
     * 
     * 调用方式参考
     * linearAnimation(oDiv, {
                "marginTop": 500,
                "marginLeft": 300
        });
     */
  function linearAnimation(ele, obj, fn) {
    clearInterval(ele.timerId)
    ele.timerId = setInterval(function () {
      // flag变量用于标记是否所有的属性都执行完了动画
      let flag = true

      for (let key in obj) {
        let target = obj[key]

        // 1.拿到元素当前的位置
        // let begin = parseInt(ele.style.width) || 0;
        let style = getComputedStyle(ele)
        // let begin = parseInt(style.width) || 0;
        let begin = parseFloat(style[key]) || 0

        // 2.定义变量记录步长
        let step = begin - target > 0 ? -13 : 13

        // 3.计算新的位置
        begin += step
        // console.log(Math.abs(target - begin), Math.abs(step));
        if (Math.abs(target - begin) > Math.abs(step)) {
          //未执行完动画
          flag = false
        } else {
          //执行完动画
          begin = target
        }

        // 4.重新设置元素的位置
        // ele.style.width = begin + "px";
        ele.style[key] = begin + 'px'
      }

      //判断动画是否执行完
      if (flag) {
        //动画执行完后关闭定时器
        clearInterval(ele.timerId)

        //判断是否传入fn函数,有才执行反之不执行
        // if(fn){
        //     fn();
        // }
        fn && fn()
      }
    }, 100)
  }

  //缓动动画
  function easeAnimation(ele, obj, fn) {
    clearInterval(ele.timerId)
    ele.timerId = setInterval(function () {
      // flag变量用于标记是否所有的属性都执行完了动画
      let flag = true

      for (let key in obj) {
        let target = obj[key]

        // 1.拿到元素当前的位置
        let style = getComputedStyle(ele)
        let begin = parseInt(style[key]) || 0

        // 2.定义变量记录步长
        // 公式: (结束位置 - 开始位置) * 缓动系数(0 ~1)
        let step = (target - begin) * 0.3

        // 3.计算新的位置
        begin += step
        if (Math.abs(Math.floor(step)) > 1) {
          flag = false
        } else {
          begin = target
        }
        // 4.重新设置元素的位置
        ele.style[key] = begin + 'px'
      }

      //判断动画是否执行完
      if (flag) {
        //动画执行完后关闭定时器
        clearInterval(ele.timerId)

        //判断是否传入fn函数,有才执行反之不执行
        fn && fn()
      }
    }, 100)
  }

  // 将函数绑定到window对象上, 这样全局就可以使用了
  window.linearAnimation = linearAnimation
  window.easeAnimation = easeAnimation
})()

使用方式:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* styles.css */
    .box {
      width: 100px;
      height: 100px;
      background-color: #3498db;
      position: relative;
      top: 0;
      left: 0;
    }
  </style>
</head>

<body>
  <div class="box" id="animatedBox"></div>
  <button onclick="startLinearAnimation()">Start Linear Animation</button>

  <script src="./utils/animate.js"></script>
  <script>
    // 获取要进行动画的元素
    const animatedBox = document.getElementById("animatedBox");

    // 定义匀速动画函数
    function startLinearAnimation() {
      // 创建一个对象,指定元素的目标位置
      const animationObj = {
        top: 200, // 垂直方向移动到200px
        left: 200, // 水平方向移动到200px
      };

      // 调用匀速动画函数
      // linearAnimation(animatedBox, animationObj, () => {
      //   console.log("Linear Animation Completed!");
      // });
      easeAnimation(animatedBox, animationObj, () => {
        console.log("Linear Animation Completed!");
      });
    }
  </script>
</body>

</html>