1. /*==ANIMATE动画库==*/
    2. ~function () {
    3. //=>准备操作CSS样式的方法 GET-CSS/SET-CSS/SET-GROUP-CSS/CSS
    4. let utils = (function () {
    5. //=>获取样式
    6. let getCss = (ele, attr) => {
    7. let val = null,
    8. reg = /^-?\d+(\.\d+)?(px|rem|em)?$/;
    9. if ('getComputedStyle' in window) {
    10. val = window.getComputedStyle(ele)[attr];
    11. if (reg.test(val)) {
    12. val = parseFloat(val);
    13. }
    14. }
    15. return val;
    16. };
    17. //=>设置样式
    18. let setCss = (ele, attr, value) => {
    19. if (!isNaN(value)) {
    20. if (!/^(opacity|zIndex)$/.test(attr)) {
    21. value += 'px';
    22. }
    23. }
    24. ele['style'][attr] = value;
    25. };
    26. //=>批量设置样式
    27. let setGroupCss = (ele, options) => {
    28. for (let attr in options) {
    29. if (options.hasOwnProperty(attr)) {
    30. setCss(ele, attr, options[attr]);
    31. }
    32. }
    33. };
    34. //=>合并为一个
    35. let css = (...arg) => {
    36. let len = arg.length,
    37. fn = getCss;
    38. if (len >= 3) {
    39. fn = setCss;
    40. }
    41. if (len === 2 && typeof arg[1] === 'object') {
    42. fn = setGroupCss;
    43. }
    44. return fn(...arg);
    45. };
    46. return {css}
    47. })();
    48. //=>EFFECT:准备运动的公式
    49. let effect = {
    50. Linear: (t, b, c, d) => t / d * c + b
    51. };
    52. //=>封装动画库
    53. window.animate = function (ele, target = {}, duration = 1000, callback = new Function()) {
    54. //=>不传递CALL-BACK,让其默认为一个空函数(回调函数:当动画结束后做什么事,都放到回调函数完成即可)
    55. if (typeof duration === 'function') {
    56. //=>我们有四个形参,但是传递的时候只传递三个,最后一个回调函数传递给duration这个参数了,我们需要改一下参数的值
    57. callback = duration;
    58. duration = 1000;
    59. }
    60. //1.基于TARGET计算出BEGIN/CHANGE
    61. let begin = {},
    62. change = {},
    63. time = 0;
    64. for (let attr in target) {
    65. if (target.hasOwnProperty(attr)) {
    66. begin[attr] = utils.css(ele, attr);
    67. change[attr] = target[attr] - begin[attr];
    68. }
    69. }
    70. //2.实现动画
    71. clearInterval(ele.animteTimer);//=>在给当前元素设置新的动画之前,先清空原有正在运行的动画(防止多动画共存,把动画的返回值赋值给当前元素的自定义属性,这样只要元素不变,我们不管啥时候在哪执行都可以清除元素的动画)
    72. ele.animteTimer = setInterval(() => {
    73. time += 17;
    74. //=>边界判断
    75. if (time >= duration) {
    76. utils.css(ele, target);
    77. clearInterval(ele.animteTimer);
    78. callback.call(ele);//=>动画完成后执行CALL-BACK(并且让回调函数中的THIS是当前操作的元素本身)
    79. return;
    80. }
    81. //=>依托TARGET计算出每个方向的当前位置
    82. let cur = {};
    83. for (let attr in target) {
    84. if (target.hasOwnProperty(attr)) {
    85. cur[attr] = effect.Linear(time, begin[attr], change[attr], duration);
    86. }
    87. }
    88. utils.css(ele, cur);
    89. }, 17);
    90. };
    91. }();