zoukankan      html  css  js  c++  java
  • 缓动动画封装详细讲解

    ---来自一个前端妹子
      1 <!DOCTYPE html>
      2 <html>
      3 <head lang="en">
      4     <meta charset="UTF-8">
      5     <title></title>
      6 
      7 
      8     <!--
      9            先快后慢
     10                 一开始的步子要迈的大,后面的步子要小
     11 
     12                 步子要越来越小
     13 
     14           被除数 / 10 ,被除数的值越大,结果就越大,被除数越小。值就越小
     15 
     16           所以我们要找到一个越来越小的数,再去除以10,把结果作为步长,就能起到步子越来越小
     17 
     18           到底什么是越来越小的值?到目标的距离,是越来越小的
     19 
     20 
     21        当前距离    目标     基数(除数)
     22          0        400       10        400 - 0 = 400  / 10   = 40   这步走40
     23         40        400       10        400 - 40 = 360 / 10 = 36   这步走36
     24 
     25         76        400       10        400 - 76 = 324  / 10 = 32.4  向上取整变成了33 这步走33
     26         109       400       10        400 - 109 = 291 / 10 = 29.1 取整变 30
     27        ………………………………………………………………………………
     28         390      400        10        400 - 390 = 10  / 10 = 1 这步走1
     29         391      400        10        400 - 391 = 9 / 10 = 0.9  向上取整走1
     30                                       越到后面越慢,而且到最后那几步就是1个像素1个像素的走,能走到,而且绝对不会超
     31 
     32        399       400      10         400 - 399 = 1    / 10   = 0.1  向上取整变1
     33 
     34     -->
     35 
     36 
     37     <style>
     38 
     39         #box {
     40             width: 100px;
     41             height: 100px;
     42             background-color: red;
     43             position: absolute;
     44         }
     45 
     46     </style>
     47 </head>
     48 <body>
     49 
     50 <input type="button" value="移动到400" id="move400"/>
     51 <input type="button" value="移动到800" id="move800"/>
     52 
     53 <div id="box"></div>
     54 
     55 </body>
     56 </html>
     57 
     58 <script>
     59 
     60     //找到div
     61     var box = document.getElementById("box");
     62 
     63     //移动到400的点击事件
     64     document.getElementById("move400").onclick = function () {
     65 
     66         animateSlow(400);
     67     }
     68 
     69 
     70     document.getElementById("move800").onclick = function () {
     71 
     72         animateSlow(800);
     73     }
     74 
     75 
     76     var timerID;
     77     function animateSlow(target) {
     78 
     79         clearInterval(timerID);
     80 
     81         timerID = setInterval(function () {
     82 
     83                     //获取到当前的位置
     84                     var current = box.offsetLeft;
     85 
     86                     //用目标 - 当前位置 得到距离 ,再用距离除以10,再向上取整得到步长
     87                     var step = Math.ceil((target - current) / 10);
     88 
     89                     //因为绝对不会超,所以算出步长后直接走这一步就行了
     90                     current += step;
     91 
     92                     //设置给要移动的元素
     93                     box.style.left = current + "px";
     94 
     95                     console.log("当前位置:" + current + "------步长:" + step);
     96 
     97                     //如果到了目的地,就停止计时器
     98                     if (current == target) {
     99 
    100                         clearInterval(timerID);
    101                     }
    102 
    103                 }, 50
    104         )
    105     }
    106 
    107 
    108 </script>
    01-缓动动画的封装之可以移动到不同的目标距离.html
    
    

    先快后慢
    一开始的步子要迈的大,后面的步子要小

    步子要越来越小

    被除数 / 10 ,被除数的值越大,结果就越大,被除数越小。值就越小

    所以我们要找到一个越来越小的数,再去除以10,把结果作为步长,就能起到步子越来越小

    到底什么是越来越小的值?到目标的距离,是越来越小的


    当前距离 目标 基数(除数)
    0 400 10 400 - 0 = 400 / 10 = 40 这步走40
    40 400 10 400 - 40 = 360 / 10 = 36 这步走36

    76 400 10 400 - 76 = 324 / 10 = 32.4 向上取整变成了33 这步走33
    109 400 10 400 - 109 = 291 / 10 = 29.1 取整变 30
    ………………………………………………………………………………
    390 400 10 400 - 390 = 10 / 10 = 1 这步走1
    391 400 10 400 - 391 = 9 / 10 = 0.9 向上取整走1
    越到后面越慢,而且到最后那几步就是1个像素1个像素的走,能走到,而且绝对不会超

    399 400 10 400 - 399 = 1 / 10 = 0.1 向上取整变1
    
    
     1 <!DOCTYPE html>
     2 <html>
     3 <head lang="en">
     4     <meta charset="UTF-8">
     5     <title></title>
     6 
     7 
     8     <style>
     9         div {
    10             width: 100px;
    11             height: 100px;
    12             background-color: red;
    13             position: absolute;
    14         }
    15 
    16         #blue {
    17             background-color: blue;
    18             top: 150px;
    19         }
    20 
    21     </style>
    22 
    23 </head>
    24 <body>
    25 
    26 <input type="button" value="移动到红" id="moveRed"/>
    27 <input type="button" value="移动到蓝" id="moveBlue"/>
    28 
    29 <div id="red"></div>
    30 <div id="blue"></div>
    31 
    32 </body>
    33 </html>
    34 
    35 <script>
    36     var red = document.getElementById("red");
    37     var blue = document.getElementById("blue");
    38 
    39     document.getElementById("moveRed").onclick = function () {
    40         animateSlow(red, 400);
    41     };
    42 
    43     document.getElementById("moveBlue").onclick = function () {
    44 
    45         animateSlow(blue, 400);
    46     };
    47 
    48 
    49 
    50     /*
    51 
    52      第二重封装:
    53         解决了可以移动不同元素的问题
    54         以及移动第二个会停止第一个元素的问题(自己的只能自己停)
    55 
    56      */
    57 
    58     function animateSlow(obj, target) {
    59 
    60         clearInterval(obj.timerID);
    61 
    62         obj.timerID = setInterval(function () {
    63 
    64                     //获取到当前的位置
    65                     var current = obj.offsetLeft;
    66 
    67                     //用目标 - 当前位置 得到距离 ,再用距离除以10,再向上取整得到步长
    68                     var step = Math.ceil((target - current) / 10);
    69 
    70                     //因为绝对不会超,所以算出步长后直接走这一步就行了
    71                     current += step;
    72 
    73                     //设置给要移动的元素
    74                     obj.style.left = current + "px";
    75 
    76                     console.log("当前位置:" + current + "------步长:" + step);
    77 
    78                     //如果到了目的地,就停止计时器
    79                     if (current == target) {
    80 
    81                         clearInterval(obj.timerID);
    82                     }
    83 
    84                 }, 50
    85         )
    86     }
    87 </script>
    02-缓动动画的封装之各种对象可以动.html
    第二重封装:
    解决了可以移动不同元素的问题
    以及移动第二个会停止第一个元素的问题(自己的只能自己停)
    
    
      1 <!DOCTYPE html>
      2 <html>
      3 <head lang="en">
      4     <meta charset="UTF-8">
      5     <title></title>
      6 
      7     <!--
      8         当前位置    目标位置   基数
      9           800        400      10    400 -800  = -400 /10 = -40
     10           760        400      10    400 - 760 = -360  / 10 = -36
     11             .....................
     12 
     13           409        400      10     400 - 409 = -9  / 10 = -0.9  向下取整变-1
     14           408        400
     15           407
     16           406
     17           400
     18 
     19           如果是往右走
     20 
     21             791      800      10     800-791 = 9 /10 = 0.9  要向上取整才正确
     22 
     23           我们发现有的时候要向上,有的时候要向下
     24 
     25           如果最终算出的结果为负数,一定要向下,如果算出的结果为正数,要向上
     26     -->
     27 
     28 
     29     <style>
     30         div {
     31             width: 100px;
     32             height: 100px;
     33             background-color: red;
     34             position: absolute;
     35         }
     36 
     37 
     38     </style>
     39 
     40 </head>
     41 <body>
     42 
     43 <input type="button" value="移动到400" id="move400"/>
     44 <input type="button" value="移动到800" id="move800"/>
     45 
     46 <div id="red"></div>
     47 
     48 </body>
     49 </html>
     50 
     51 <script>
     52     var red = document.getElementById("red");
     53     var blue = document.getElementById("blue");
     54 
     55     document.getElementById("move400").onclick = function () {
     56 
     57         animateSlow(red, 400);
     58     };
     59 
     60     document.getElementById("move800").onclick = function () {
     61 
     62         animateSlow(red, 800);
     63     };
     64 
     65 
     66     /*
     67 
     68      第三重封装:
     69      解决了既可以往右走,也可以往走的问题
     70 
     71      发现:只要看算出的结果,如果是正就要向上取整,如果是负就要向下取整
     72 
     73 
     74 
     75      */
     76 
     77     function animateSlow(obj, target) {
     78 
     79         clearInterval(obj.timerID);
     80 
     81         obj.timerID = setInterval(function () {
     82 
     83                     //获取到当前的位置
     84                     var current = obj.offsetLeft;
     85 
     86                     //先用目标-当前位置,再除以基数得到结果
     87                     var result = (target - current) / 10;
     88 
     89                     //如果结果是正就用向上取整,如果是负就用 向下取整
     90                     var step = result > 0 ? Math.ceil(result) : Math.floor(result);
     91 
     92                     //因为绝对不会超,所以算出步长后直接走这一步就行了
     93                     current += step;
     94 
     95                     //设置给要移动的元素
     96                     obj.style.left = current + "px";
     97 
     98                     console.log("当前位置:" + current + "------步长:" + step);
     99 
    100                     //如果到了目的地,就停止计时器
    101                     if (current == target) {
    102 
    103                         clearInterval(obj.timerID);
    104                     }
    105 
    106                 }, 50
    107         )
    108     }
    109 </script>
    03-缓动动画的封装完成往左往右动.html
    当前位置    目标位置   基数
    800 400 10 400 -800 = -400 /10 = -40
    760 400 10 400 - 760 = -360 / 10 = -36
    .....................

    409 400 10 400 - 409 = -9 / 10 = -0.9 向下取整变-1
    408 400
    407
    406
    400

    如果是往右走

    791 800 10 800-791 = 9 /10 = 0.9 要向上取整才正确

    我们发现有的时候要向上,有的时候要向下

    如果最终算出的结果为负数,一定要向下,如果算出的结果为正数,要向上

    第三重封装:
    解决了既可以往右走,也可以往走的问题

    发现:只要看算出的结果,如果是正就要向上取整,如果是负就要向下取整



      1 <!DOCTYPE html>
      2 <html>
      3 <head lang="en">
      4     <meta charset="UTF-8">
      5     <title></title>
      6 
      7     <style>
      8         #box {
      9             width: 100px;
     10             height: 100px;
     11             background-color: red;
     12             position: absolute;
     13         }
     14 
     15         /*
     16             第四重封装:
     17                    解决了可以改动上下移动和左右移动以及宽高变化的问题
     18 
     19                    加一个参数:参数传入一个你需要改动的属性
     20 
     21                    然后再通过我们封装的获取样式的方法,获取到当前的值
     22                    算法不变
     23 
     24                    只不过赋值时,就根据你传入的参数来赋值到对应的属性
     25 
     26         */
     27     </style>
     28 </head>
     29 <body>
     30 
     31 <input type="button" value="向下走500" id="down500"/>
     32 <input type="button" value="向右走500" id="right500"/>
     33 <input type="button" value="变宽到400" id="width400"/>
     34 <input type="button" value="变高到400" id="height400"/>
     35 
     36 <div id="box"></div>
     37 
     38 </body>
     39 </html>
     40 
     41 
     42 <script src="common.js"></script>
     43 <script>
     44     //找到div
     45     var box = document.getElementById("box");
     46 
     47     document.getElementById("down500").onclick = function () {
     48 
     49         animateSlow(box, 500, "top");
     50     };
     51 
     52 
     53     document.getElementById("right500").onclick = function () {
     54 
     55         animateSlow(box, 500, "left");
     56     };
     57 
     58     document.getElementById("width400").onclick = function () {
     59 
     60         animateSlow(box, 400, "width");
     61     };
     62 
     63     document.getElementById("height400").onclick = function () {
     64 
     65         animateSlow(box, 400, "height");
     66     };
     67 
     68 
     69     function animateSlow(obj, target, attr) {//可能传left,也可能传top
     70 
     71         clearInterval(obj.timerID);
     72 
     73         obj.timerID = setInterval(function () {
     74 
     75                     //获取到当前的位置
     76                     //传入的是什么属性就获取什么属性的样式,因为得到的是带单位的字符串,所以要用parseInt做一个转换
     77                     var current = parseInt(getStyle(obj, attr));
     78 
     79                     //先用目标-当前位置,再除以基数得到结果
     80                     var result = (target - current) / 10;
     81 
     82                     //如果结果是正就用向上取整,如果是负就用 向下取整
     83                     var step = result > 0 ? Math.ceil(result) : Math.floor(result);
     84 
     85                     //因为绝对不会超,所以算出步长后直接走这一步就行了
     86                     current += step;
     87 
     88                     //设置给要移动的元素
     89                     obj.style[attr] = current + "px";
     90 
     91                     console.log("当前位置:" + current + "------步长:" + step);
     92 
     93                     //如果到了目的地,就停止计时器
     94                     if (current == target) {
     95 
     96                         clearInterval(obj.timerID);
     97                     }
     98 
     99                 }, 50
    100         )
    101     }
    102 </script>
    04-缓动动画的封装之实现上下宽高可以用动画变化.html
    第四重封装:
    解决了可以改动上下移动和左右移动以及宽高变化的问题

    加一个参数:参数传入一个你需要改动的属性

    然后再通过我们封装的获取样式的方法,获取到当前的值
    算法不变

    只不过赋值时,就根据你传入的参数来赋值到对应的属性
    
    
      1 <!DOCTYPE html>
      2 <html>
      3 <head lang="en">
      4     <meta charset="UTF-8">
      5     <title></title>
      6 
      7     <style>
      8         #box {
      9             width: 100px;
     10             height: 100px;
     11             background-color: red;
     12             position: absolute;
     13         }
     14 
     15         /*
     16             第五重封装:
     17                    解决了可以同时改多个属性的问题
     18 
     19                    1.把函数的参数精简为2个,1个为接受要改的元素,第二个就是接收对象
     20                             对象里面放你要改的属性(对象的属性)和它对应的目标(属性的值)
     21 
     22                    2.在计时器里遍历接收对象的那个参数,取到key,key就是我们要取到的样式的属性,以及要改的属性
     23                         算法不变,只是取属性时用key来取了
     24 
     25                    3.不能哪一个到了目标就停止计时器,而应该是全部到了才停止计时器
     26                         用一个标记来标记,只要有一个没到,就改成false,循环外面判断是否还是为true,还是为true就代表都到了,都到了就停止计时器
     27 
     28         */
     29     </style>
     30 </head>
     31 <body>
     32 
     33 <input type="button" value="同时向右走到500向下走到400" id="btn"/>
     34 
     35 
     36 <div id="box"></div>
     37 
     38 </body>
     39 </html>
     40 
     41 
     42 <script src="common.js"></script>
     43 <script>
     44 
     45 
     46     //找到div
     47     var box = document.getElementById("box");
     48 
     49     document.getElementById("btn").onclick = function () {
     50 
     51         /*
     52          我们现在需要同时改多个属性,而且多个属性可能有不同的不表
     53          那么如果用以前的那种加参数方式不行,因为假如说要改3个属性,就需要6个,到时再临时加参数肯定不行
     54          我想用一个参数,既可以让你传入一个属性和一个目标
     55          也可以传入多个属性加多个目标
     56          */
     57 
     58         var att = {
     59 
     60             left: 500,
     61             top: 400,
     62              400,
     63             height: 400,
     64         }
     65 
     66         animateSlow(box, att);
     67     };
     68 
     69 
     70     function animateSlow(obj, attrs) {//可能传left,也可能传top
     71 
     72         clearInterval(obj.timerID);
     73 
     74         obj.timerID = setInterval(function () {
     75 
     76             //我先默认认为所有的都到了目的地(标记为true),在循环里,我判断一下,只要有一个不到,我就把标记改为false
     77 
     78             //默认先认为都到了
     79             var flag = true;
     80 
     81             //把所有的属性名取出来
     82             for (var key in attrs) { //        left: 500  top: 400
     83 
     84                 //获取到当前的位置
     85                 //传入的是什么属性就获取什么属性的样式,因为得到的是带单位的字符串,所以要用parseInt做一个转换
     86                 var current = parseInt(getStyle(obj, key));
     87 
     88                 //先用目标-当前位置,再除以基数得到结果
     89                 //注意:此时目标是它的key所对应的值
     90                 var result = (attrs[key] - current) / 10;
     91 
     92                 //如果结果是正就用向上取整,如果是负就用 向下取整
     93                 var step = result > 0 ? Math.ceil(result) : Math.floor(result);
     94 
     95                 //因为绝对不会超,所以算出步长后直接走这一步就行了
     96                 current += step;
     97 
     98                 //设置给要移动的元素
     99                 obj.style[key] = current + "px";
    100 
    101                 console.log("当前位置:" + current + "------步长:" + step);
    102 
    103                 //只要有一个没到,就不要停计时器
    104                 if (current != attrs[key]) {
    105 
    106                     flag = false;
    107                 }
    108             }
    109 
    110             //如果这个值还是为true,就代表所有的属性都到了目的地
    111             if (flag) {
    112 
    113                 clearInterval(obj.timerID);
    114             }
    115 
    116         }, 50)
    117     }
    118 </script>
    05-缓动动画的封装之实现斜着走.html
    第五重封装:
    我们现在需要同时改多个属性,而且多个属性可能有不同的不表
    那么如果用以前的那种加参数方式不行,因为假如说要改3个属性,就需要6个,到时再临时加参数肯定不行
    我想用一个参数,既可以让你传入一个属性和一个目标
    也可以传入多个属性加多个目标
      1 <!DOCTYPE html>
      2 <html>
      3 <head lang="en">
      4     <meta charset="UTF-8">
      5     <title></title>
      6 
      7 
      8     <!--
      9         这一重解决了:
     10             1.透明度不可以改的问题(解决为可以改)
     11                    1.1 因为透明度特殊,所以单独在forin里用一个if判断,如果key等于opacity,那么就走opacity的代码,else就走以前写的代码
     12                    1.2 在opacity里,代码跟以前的代码几乎一样,只改动以下几个部分
     13                         1.2.1 把parseInt改成parseFloat ,再取到值以后给当前位置和目标位置先乘以100
     14                         1.2.2 在赋值到元素的opacity之前,先除以100
     15                         1.2.3 在赋值时去掉px
     16 
     17 
     18             2.增加动画完成后可以执行你想做的事的代码(回调函数)
     19                 2.1 先增加一个参数,用来接收用户传入的函数
     20                 2.2 在清除计时器的代码后面,先判断是不是函数,如果是,就调用
     21 
     22     -->
     23 
     24     <style>
     25         #box {
     26             width: 100px;
     27             height: 100px;
     28             background-color: red;
     29             position: absolute;
     30         }
     31 
     32     </style>
     33 </head>
     34 <body>
     35 
     36 <input type="button" value="同时向右走到500向下走到400" id="btn"/>
     37 
     38 
     39 <div id="box"></div>
     40 
     41 </body>
     42 </html>
     43 
     44 
     45 <script src="common.js"></script>
     46 <script>
     47 
     48 
     49     //找到div
     50     var box = document.getElementById("box");
     51 
     52     document.getElementById("btn").onclick = function () {
     53 
     54         /*
     55          我们现在需要同时改多个属性,而且多个属性可能有不同的不表
     56          那么如果用以前的那种加参数方式不行,因为假如说要改3个属性,就需要6个,到时再临时加参数肯定不行
     57          我想用一个参数,既可以让你传入一个属性和一个目标
     58          也可以传入多个属性加多个目标
     59          */
     60 
     61         var att = {
     62 
     63             opacity: 0,
     64             left: 500,
     65             top: 400,
     66              300,
     67             height: 300
     68         }
     69 
     70         animateSlow(box, att, function () {
     71 
     72             var attrs = {
     73 
     74                 top: 31,
     75                 left: 1000,
     76                  100,
     77                 height: 100,
     78                 opacity: 1
     79             }
     80             animateSlow(box, attrs);
     81         });
     82     };
     83 
     84 
     85     function animateSlow(obj, attrs, fn) {//可能传left,也可能传top
     86 
     87         clearInterval(obj.timerID);
     88 
     89         obj.timerID = setInterval(function () {
     90 
     91             //我先默认认为所有的都到了目的地(标记为true),在循环里,我判断一下,只要有一个不到,我就把标记改为false
     92 
     93             //默认先认为都到了
     94             var flag = true;
     95 
     96             //把所有的属性名取出来
     97             for (var key in attrs) { //        left: 500  top: 400
     98 
     99                 if (key == "opacity") {
    100 
    101                     //获取到当前的位置
    102                     //传入的是什么属性就获取什么属性的样式,因为得到的是带单位的字符串,所以要用parseInt做一个转换
    103                     var current = parseFloat(getStyle(obj, key)) * 100;
    104 
    105                     //它的值太小了
    106 //先用目标-当前位置,再除以基数得到结果
    107                     //注意:此时目标是它的key所对应的值
    108                     var result = (attrs[key] * 100 - current) / 10;
    109 
    110                     //如果结果是正就用向上取整,如果是负就用 向下取整
    111                     var step = result > 0 ? Math.ceil(result) : Math.floor(result);
    112 
    113                     //因为绝对不会超,所以算出步长后直接走这一步就行了
    114                     current += step;
    115 
    116                     //之前你是先乘以100做的运算,所以后面应该把再除以100
    117                     current /= 100;
    118                     //设置给要移动的元素
    119                     obj.style[key] = current;
    120 
    121                     console.log("当前位置:" + current + "------步长:" + step);
    122 
    123                     //只要有一个没到,就不要停计时器
    124                     if (current != attrs[key]) {
    125 
    126                         flag = false;
    127                     }
    128 
    129                 } else {
    130 
    131                     //获取到当前的位置
    132                     //传入的是什么属性就获取什么属性的样式,因为得到的是带单位的字符串,所以要用parseInt做一个转换
    133                     var current = parseInt(getStyle(obj, key));
    134 
    135                     //先用目标-当前位置,再除以基数得到结果
    136                     //注意:此时目标是它的key所对应的值
    137                     var result = (attrs[key] - current) / 10;
    138 
    139                     //如果结果是正就用向上取整,如果是负就用 向下取整
    140                     var step = result > 0 ? Math.ceil(result) : Math.floor(result);
    141 
    142                     //因为绝对不会超,所以算出步长后直接走这一步就行了
    143                     current += step;
    144 
    145                     //设置给要移动的元素
    146                     obj.style[key] = current + "px";
    147 
    148                     console.log("当前位置:" + current + "------步长:" + step);
    149 
    150                     //只要有一个没到,就不要停计时器
    151                     if (current != attrs[key]) {
    152 
    153                         flag = false;
    154                     }
    155                 }
    156             }
    157 
    158             //如果这个值还是为true,就代表所有的属性都到了目的地
    159             if (flag) {
    160 
    161                 clearInterval(obj.timerID);
    162 
    163                 //这里的代码不要写死,就让别人把要结束时执行的代码传进来
    164                 //你传的是什么代码,我执行的就是什么代码
    165                 if (fn instanceof  Function) {
    166                     fn();
    167                 }
    168 
    169             }
    170 
    171         }, 50)
    172     }
    173 </script>
    06-缓动动画的封装终极封装.html
    这一重解决了:
    1.透明度不可以改的问题(解决为可以改)
    1.1 因为透明度特殊,所以单独在forin里用一个if判断,如果key等于opacity,那么就走opacity的代码,else就走以前写的代码
    1.2 在opacity里,代码跟以前的代码几乎一样,只改动以下几个部分
    1.2.1 把parseInt改成parseFloat ,再取到值以后给当前位置和目标位置先乘以100
    1.2.2 在赋值到元素的opacity之前,先除以100
    1.2.3 在赋值时去掉px


    2.增加动画完成后可以执行你想做的事的代码(回调函数)
    2.1 先增加一个参数,用来接收用户传入的函数
    2.2 在清除计时器的代码后面,先判断是不是函数,如果是,就调用
  • 相关阅读:
    添加鼠标右键菜单项(EditPlus为例)
    spring 定时器Quartz
    python脚本基础总结
    python2.7.9基础学习
    Vagrant+virtualBox+pycham+python环境的安装及配置
    python
    spring资料
    Java四种线程池的使用
    echarts学习网站
    hashmap两种遍历方法
  • 原文地址:https://www.cnblogs.com/DZzzz/p/8167260.html
Copyright © 2011-2022 走看看