文章目录

  • 一、元素偏移量offest系列
  • 🥇offset与style的区别
  • 🎓案例1
  • 🦹🏽♂️案例2
  • 🐼案例3
  • 二、元素可视区client系列
  • 三、元素滚动scroll系列
  • 🏂🏿案例4:
  • 🔭补充 mouseenter事件
  • 四、动画函数封装
  • 💎动画函数简单封装操作
  • ☯️缓动动画原理
  • 🎅🏾缓动动画多个目标之间移动
  • 🍂动画函数添加回调函数
  • 🦦动画函数封装到单独JS文件里面



一、元素偏移量offest系列

offset系列相关属性可以动态的得到该元素的位置(偏移量)、大小等

  • 获取元素举例带有定位父元素的位置
  • 获取元年苏自身的大小(宽度,高度)
  • 注意:返回的数值都不带单位

javascript网页特效手册下载 js实现网页特效_html

实际运用:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }

      .father {
        position: relative;
        width: 200px;
        height: 200px;
        background-color: pink;
        margin: 100px;
      }

      .son {
        width: 100px;
        height: 100px;
        background-color: blue;
        margin-left: 45px;
      }

      .w {
        width: 200px;
        height: 200px;
        background-color: skyblue;
        margin: 0 auto 200px;
        padding: 10px;
        border: 10px solid red;
      }
    </style>
  </head>
  <body>
    <div class="father">
      <div class="son"></div>
    </div>
    <div class="w"></div>
    <script>
      var father = document.querySelector(".father");
      var son = document.querySelector(".son");
      //offset 系列
      console.log(father.offsetTop);
      console.log(father.offsetLeft);
      //以带有定位的父亲为准,如果没有父亲或者没有定位,则以body为准
      console.log(son.offsetLeft);
      //可以得到元素的大小 宽度和高度
      var w = document.querySelector(".w");
      console.log(w.offsetWidth);
      console.log(w.offsetHeight);  //padding和border都会对大小产生影响
      //返回带有定位的父亲,否则返回的是body
      console.log(son.offsetParent);
      console.log(son.parentNode);  //返回最近一级的父亲,不管父亲有没有定位
    </script>
  </body>
</html>

结果如下:

javascript网页特效手册下载 js实现网页特效_javascript_02

🥇offset与style的区别

javascript网页特效手册下载 js实现网页特效_前端_03

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            width: 200px;
            height: 200px;
            background-color: pink;
        }
    </style>
</head>
<body>
    <div class="box"></div>
    <script>
        //offset与style的区别
        var box=document.querySelector('.box')
        console.log(box.offsetWidth);
        console.log(box.style.width);
        //offset是只读属性
        box.style.width="300px" //一定要用引号引起来
    </script>
</body>
</html>

🎓案例1

获取鼠标在盒子内的坐标

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .box {
        width: 300px;
        height: 300px;
        background-color: pink;
        margin: 200px;
      }
    </style>
  </head>
  <body>
    <div class="box"></div>
    <script>
      var box = document.querySelector(".box");
      box.addEventListener("mousemove", function (e) {
        // console.log(e.pageX);
        // console.log(e.pageY);
        // console.log(box.offsetLeft);
        var x = e.pageX - this.offsetLeft;
        var y = e.pageY - this.offsetTop;
        this.innerHTML = "x的坐标是" + x + "y的坐标是" + y;
      });
    </script>
  </body>
</html>

效果如下:

javascript网页特效手册下载 js实现网页特效_javascript_04

🦹🏽♂️案例2

模态框拖拽

<!DOCTYPE html>
<html>
  <head lang="en">
    <meta charset="UTF-8" />
    <title></title>
    <style>
      .login-header {
        width: 100%;
        text-align: center;
        height: 30px;
        font-size: 24px;
        line-height: 30px;
      }

      ul,
      li,
      ol,
      dl,
      dt,
      dd,
      div,
      p,
      span,
      h1,
      h2,
      h3,
      h4,
      h5,
      h6,
      a {
        padding: 0px;
        margin: 0px;
      }

      .login {
        display: none;
        width: 512px;
        height: 280px;
        position: fixed;
        border: #ebebeb solid 1px;
        left: 50%;
        top: 50%;
        background: #ffffff;
        box-shadow: 0px 0px 20px #ddd;
        z-index: 9999;
        transform: translate(-50%, -50%);
      }

      .login-title {
        width: 100%;
        margin: 10px 0px 0px 0px;
        text-align: center;
        line-height: 40px;
        height: 40px;
        font-size: 18px;
        position: relative;
        cursor: move;
      }

      .login-input-content {
        margin-top: 20px;
      }

      .login-button {
        width: 50%;
        margin: 30px auto 0px auto;
        line-height: 40px;
        font-size: 14px;
        border: #ebebeb 1px solid;
        text-align: center;
      }

      .login-bg {
        display: none;
        width: 100%;
        height: 100%;
        position: fixed;
        top: 0px;
        left: 0px;
        background: rgba(0, 0, 0, 0.3);
      }

      a {
        text-decoration: none;
        color: #000000;
      }

      .login-button a {
        display: block;
      }

      .login-input input.list-input {
        float: left;
        line-height: 35px;
        height: 35px;
        width: 350px;
        border: #ebebeb 1px solid;
        text-indent: 5px;
      }

      .login-input {
        overflow: hidden;
        margin: 0px 0px 20px 0px;
      }

      .login-input label {
        float: left;
        width: 90px;
        padding-right: 10px;
        text-align: right;
        line-height: 35px;
        height: 35px;
        font-size: 14px;
      }

      .login-title span {
        position: absolute;
        font-size: 12px;
        right: -20px;
        top: -30px;
        background: #ffffff;
        border: #ebebeb solid 1px;
        width: 40px;
        height: 40px;
        border-radius: 20px;
      }
    </style>
  </head>

  <body>
    <div class="login-header">
      <a id="link" href="javascript:;">点击,弹出登录框</a>
    </div>
    <div id="login" class="login">
      <div id="title" class="login-title">
        登录会员
        <span
          ><a id="closeBtn" href="javascript:void(0);" class="close-login"
            >关闭</a
          ></span
        >
      </div>
      <div class="login-input-content">
        <div class="login-input">
          <label>用户名:</label>
          <input
            type="text"
            placeholder="请输入用户名"
            name="info[username]"
            id="username"
            class="list-input"
          />
        </div>
        <div class="login-input">
          <label>登录密码:</label>
          <input
            type="password"
            placeholder="请输入登录密码"
            name="info[password]"
            id="password"
            class="list-input"
          />
        </div>
      </div>
      <div id="loginBtn" class="login-button">
        <a href="javascript:void(0);" id="login-button-submit">登录会员</a>
      </div>
    </div>
    <!-- 遮盖层 -->
    <div id="bg" class="login-bg"></div>
    <script>
      // 1. 获取元素
      var login = document.querySelector(".login");
      var mask = document.querySelector(".login-bg");
      var link = document.querySelector("#link");
      var closeBtn = document.querySelector("#closeBtn");
      var title = document.querySelector("#title");
      // 2. 点击弹出层这个链接 link  让mask 和login 显示出来
      link.addEventListener("click", function () {
        mask.style.display = "block";
        login.style.display = "block";
      });
      // 3. 点击 closeBtn 就隐藏 mask 和 login
      closeBtn.addEventListener("click", function () {
        mask.style.display = "none";
        login.style.display = "none";
      });
      // 4. 开始拖拽
      // (1) 当我们鼠标按下, 就获得鼠标在盒子内的坐标
      title.addEventListener("mousedown", function (e) {
        var x = e.pageX - login.offsetLeft;
        var y = e.pageY - login.offsetTop;
        // (2) 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top值
        document.addEventListener("mousemove", move);

        function move(e) {
          login.style.left = e.pageX - x + "px";
          login.style.top = e.pageY - y + "px";
        }
        // (3) 鼠标弹起,就让鼠标移动事件移除
        document.addEventListener("mouseup", function () {
          document.removeEventListener("mousemove", move);
        });
      });
    </script>
  </body>
</html>

效果如下:

javascript网页特效手册下载 js实现网页特效_javascript_05

中间模块可拖动

🐼案例3

京东放大镜(是前两个案例的综合实现)


二、元素可视区client系列

作用:获取元素的大小,边框的大小

javascript网页特效手册下载 js实现网页特效_html_06

client和offset最大的区别就是不包含边框

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            background-color: pink;
        }
    </style>
</head>
<body>
    <div></div>
    <script>
        var div=document.querySelector('div')
        console.log(div.clientWidth);
    </script>
</body>
</html>

立即执行函数:

不需要调用,能够了立马自己执行

立即执行函数最大的作用就算独立创建了一个作用域,里面所有的变量都是局部变量,不会有命名冲突的情况

语法1:

<script>
        //写法1
        (function() {
            console.log();
        })()
    </script>

语法2:

<script>
    //语法2:
        (function sum(){

        }())
    </script>

示例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      //也可以传递参数
      (function (a, b) {	//匿名函数
        console.log(a + b);
      })(1, 2);
      
      (function sum(a, b) {
        console.log(a + b);
      })(2, 3);
    </script>
  </body>
</html>

三、元素滚动scroll系列

作用:可以动态的得到元素的大小,滚动举例等

javascript网页特效手册下载 js实现网页特效_前端_07

示例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      div {
        width: 200px;
        height: 200px;
        background-color: pink;
        border: 10px solid red;
        padding: 10px;
        overflow: auto;
      }
    </style>
  </head>
  <body>
    <div>
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
      我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
    </div>
    <script>
      var div = document.querySelector("div");
      console.log(div.scrollHeight);
      console.log(div.clientHeight);
      console.log(div.scrollTop);
      //滚动事件当我们滚动条发生变化会触发的事件
    </script>
  </body>
</html>

🏂🏿案例4:

仿淘宝固定侧边栏(有兼容性问题)

<!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>Document</title>
    <style>
      .slider-bar {
        position: absolute;
        left: 50%;
        top: 300px;
        margin-left: 600px;
        width: 45px;
        height: 130px;
        background-color: pink;
      }

      .w {
        width: 1200px;
        margin: 10px auto;
      }

      .header {
        height: 150px;
        background-color: purple;
      }

      .banner {
        height: 250px;
        background-color: skyblue;
      }

      .main {
        height: 1000px;
        background-color: yellowgreen;
      }

      span {
        display: none;
        position: absolute;
        bottom: 0;
      }
    </style>
  </head>

  <body>
    <div class="slider-bar">
      <span class="goBack">返回顶部</span>
    </div>
    <div class="header w">头部区域</div>
    <div class="banner w">banner区域</div>
    <div class="main w">主体部分</div>
    <script>
      //1. 获取元素
      var sliderbar = document.querySelector(".slider-bar");
      var banner = document.querySelector(".banner");
      // banner.offestTop 就是被卷去头部的大小 一定要写到滚动的外面
      var bannerTop = banner.offsetTop;
      // 当我们侧边栏固定定位之后应该变化的数值
      var sliderbarTop = sliderbar.offsetTop - bannerTop;
      // 获取main 主体元素
      var main = document.querySelector(".main");
      var goBack = document.querySelector(".goBack");
      var mainTop = main.offsetTop;
      // 2. 页面滚动事件 scroll
      document.addEventListener("scroll", function () {
        // console.log(11);
        // window.pageYOffset 页面被卷去的头部
        // console.log(window.pageYOffset);
        // 3 .当我们页面被卷去的头部大于等于了 172 此时 侧边栏就要改为固定定位
        if (window.pageYOffset >= bannerTop) {
          sliderbar.style.position = "fixed";
          sliderbar.style.top = sliderbarTop + "px";
        } else {
          sliderbar.style.position = "absolute";
          sliderbar.style.top = "300px";
        }
        // 4. 当我们页面滚动到main盒子,就显示 goback模块
        if (window.pageYOffset >= mainTop) {
          goBack.style.display = "block";
        } else {
          goBack.style.display = "none";
        }
      });
    </script>
  </body>
</html>

存在侧边栏文字显示不出来的问题,可以通过封装自定义函数解决

🔭补充 mouseenter事件

当鼠标移动到元素上就会触发mouseenter事件
类似mouseover,两者事件的区别是
mouseenter鼠标经过自身盒子会触发,经过子盒子还会触发,mouseenter只会经过自身盒子触发

四、动画函数封装

核心原理:

通过定时器setInterval()不断移动盒子位置

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      div {
        position: absolute;
        left: 0;
        width: 100px;
        height: 100px;
        background-color: pink;
      }
    </style>
  </head>
  <body>
    <div></div>
    <script>
      var div = document.querySelector("div");
      var timer = setInterval(function () {
        if (div.offsetLeft >= 400) {    //实现停止动画
          clearInterval(timer);
        }
        div.style.left = div.offsetLeft + 1 + "px";	//不要忘记单位
      }, 10);
    </script>
  </body>
</html>

💎动画函数简单封装操作

动画函数封装的好处
可以个模块同时使用,不相互冲突

示例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* 动画中必须加定位 */
      div {
        position: absolute;
        left: 0;
        width: 100px;
        height: 100px;
        background-color: pink;
      }

      span {
        position: absolute;
        left: 0;
        top: 200px;
        display: block;
        width: 150px;
        height: 150px;
        background-color: purple;
      }
    </style>
  </head>
  <body>
    <div></div>
    <span></span>
    <script>
      function animate(obj, target) {
        var timer = setInterval(function () {
          if (obj.offsetLeft >= target) {
            //实现停止动画
            clearInterval(obj.timer);
          }
          obj.style.left = obj.offsetLeft + 1 + "px";
        }, 10);
      }
      var div = document.querySelector("div");
      var span = document.querySelector("span");
      //调用函数
      animate(div, 300);
      animate(span, 800);
    </script>
  </body>
</html>

具体效果为两个小块同向匀速运动

动画中必须加定位,absolute和relative都可以

利用给对象添加属性的方法对函数进行赋值操作

但程序存在一个小bug
例如下面这段代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* 动画中必须加定位 */
      div {
        position: absolute;
        left: 0;
        width: 100px;
        height: 100px;
        background-color: pink;
      }

      span {
        position: absolute;
        left: 0;
        top: 200px;
        display: block;
        width: 150px;
        height: 150px;
        background-color: purple;
      }
    </style>
  </head>
  <body>
    <button>点击下面</button>
    <div></div>
    <span></span>
    <script>
      function animate(obj, target) {
        //给不同的元素指定了不同的定时器
        obj.timer = setInterval(function () {
          if (obj.offsetLeft >= target) {
            //实现停止动画
            clearInterval(obj.timer);
          }
          obj.style.left = obj.offsetLeft + 1 + "px";
        }, 10);
      }

      var div = document.querySelector("div");
      var span = document.querySelector("span");
      var btn = document.querySelector("button");
      //调用函数
      animate(div, 300);
      btn.addEventListener("click", function () {
        animate(span, 1800);
      });
    </script>
  </body>
</html>

点击次数越多,紫块走得越快

javascript网页特效手册下载 js实现网页特效_css_08

解决方法就是每次调用函数前清除以前的定时器,保留当前的定时器执行

添加如下代码:

clearInterval(obj.timer)

☯️缓动动画原理

缓动动画就是让元素的运动速度有变化,最常见的是让速度慢慢停下来

核心算法:
(目标值-现在的位置)/10 作为每次移动的步长

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* 动画中必须加定位 */
      div {
        position: absolute;
        left: 0;
        width: 100px;
        height: 100px;
        background-color: pink;
      }

      span {
        position: absolute;
        left: 0;
        top: 200px;
        display: block;
        width: 150px;
        height: 150px;
        background-color: purple;
      }
    </style>
  </head>
  <body>
    <button>点击下面</button>
    <div></div>
    <span></span>
    <script>
      function animate(obj, target) {
        //给不同的元素指定了不同的定时器
        clearInterval(obj.timer);
        obj.timer = setInterval(function () {
          //步长值写到定时器内部
          var step = (target - obj.offsetLeft) / 10;
          if (obj.offsetLeft >= target) {
            //实现停止动画
            clearInterval(obj.timer);
          }
          //把每次加1的步长值,改为一个慢慢变小的值
          obj.style.left = obj.offsetLeft + step + "px";
        }, 30);
      }

      var div = document.querySelector("div");
      var span = document.querySelector("span");
      var btn = document.querySelector("button");
      //调用函数
      animate(div, 300);
      btn.addEventListener("click", function () {
        animate(span, 1800);
      });
    </script>
  </body>
</html>

🎅🏾缓动动画多个目标之间移动

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* 动画中必须加定位 */
      div {
        position: absolute;
        left: 0;
        width: 100px;
        height: 100px;
        background-color: pink;
      }

      span {
        position: absolute;
        left: 0;
        top: 200px;
        display: block;
        width: 150px;
        height: 150px;
        background-color: purple;
      }
    </style>
  </head>
  <body>
    <button class="btn500">500</button>
    <button class="btn800">800</button>
    <div></div>
    <span></span>
    <script>
      function animate(obj, target) {
        //给不同的元素指定了不同的定时器
        clearInterval(obj.timer);
        obj.timer = setInterval(function () {
          //步长值写到定时器内部
          var step = Math.ceil((target - obj.offsetLeft) / 10);
          if (obj.offsetLeft >= target) {
            //实现停止动画
            clearInterval(obj.timer);
          }
          //把每次加1的步长值,改为一个慢慢变小的值
          obj.style.left = obj.offsetLeft + step + "px";
        }, 30);
      }

      var div = document.querySelector("div");
      var span = document.querySelector("span");
      var btn500 = document.querySelector(".btn500");
      var btn800 = document.querySelector(".btn800");
      //调用函数
      animate(div, 300);
      btn500.addEventListener("click", function () {
        animate(span, 500);
      });
      btn800.addEventListener("click", function () {
        animate(span, 800);
      });
    </script>
  </body>
</html>

因为小数的原因不会回到原位
所以需要一个判断条件

step = step > 0 ? Math.ceil(step) : Math.floor(step);

🍂动画函数添加回调函数

<!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>Document</title>
    <style>
      div {
        position: absolute;
        left: 0;
        width: 100px;
        height: 100px;
        background-color: pink;
      }

      span {
        position: absolute;
        left: 0;
        top: 200px;
        display: block;
        width: 150px;
        height: 150px;
        background-color: purple;
      }
    </style>
  </head>

  <body>
    <button class="btn500">点击夏雨荷到500</button>
    <button class="btn800">点击夏雨荷到800</button>
    <span>夏雨荷</span>
    <script>
      // 缓动动画函数封装obj目标对象 target 目标位置
      // 思路:
      // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
      // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
      // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
      function animate(obj, target, callback) {
        // console.log(callback);  callback = function() {}  调用的时候 callback()

        // 先清除以前的定时器,只保留当前的一个定时器执行
        clearInterval(obj.timer);
        obj.timer = setInterval(function () {
          // 步长值写到定时器的里面
          // 把我们步长值改为整数 不要出现小数的问题
          // var step = Math.ceil((target - obj.offsetLeft) / 10);
          var step = (target - obj.offsetLeft) / 10;
          step = step > 0 ? Math.ceil(step) : Math.floor(step);
          if (obj.offsetLeft == target) {
            // 停止动画 本质是停止定时器
            clearInterval(obj.timer);
            // 回调函数写到定时器结束里面
            if (callback) {
              // 调用函数
              callback();
            }
          }
          // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
          obj.style.left = obj.offsetLeft + step + "px";
        }, 15);
      }
      var span = document.querySelector("span");
      var btn500 = document.querySelector(".btn500");
      var btn800 = document.querySelector(".btn800");

      btn500.addEventListener("click", function () {
        // 调用函数
        animate(span, 500);
      });
      btn800.addEventListener("click", function () {
        // 调用函数
        animate(span, 800, function () {
          // alert('你好吗');
          span.style.backgroundColor = "red";
        });
      });
      // 匀速动画 就是 盒子是当前的位置 +  固定的值 10
      // 缓动动画就是  盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
    </script>
  </body>
</html>

🦦动画函数封装到单独JS文件里面

因为以后经常使用动画特效,可以单独封装到一个JS文件里面,使用的时候引用这个JS文件