zoukankan      html  css  js  c++  java
  • move.js 源码 学习笔记

    源码笔记:

      1 /* move.js
      2  * @author:flfwzgl https://github.com/flfwzgl
      3  * @copyright: MIT license 
      4  * Sorrow.X --- 添加注释,注释纯属个人理解(源码有稍微改动,方便阅读)
      5  * */
      6 
      7 ! function() {
      8 
      9     var PI = Math.PI,
     10         sin = Math.sin,
     11         cos = Math.cos,
     12         pow = Math.pow,
     13         abs = Math.abs,
     14         sqrt = Math.sqrt;
     15 
     16     var request = window.requestAnimationFrame,
     17         stopRequest = window.cancelAnimationFrame;
     18     var _move, _stopMove;    // 都是函数, 不支持requestAnimationFrame的浏览器就使用定时器
     19 
     20     //初始化运动函数和停止函数  
     21     if (request) {
     22         _move = function(fn, timer) {    // fn: 匿名函数, timer: 不同的空对象
     23             var step = function() {
     24                 if (!fn()) {    // fn函数返回值为假值则调用requestAnimationFrame方法(true代表运动结束)
     25                     timer.id = request(step);
     26                 };
     27             };
     28             step();    // 函数调用
     29         };
     30     } else {
     31         _move = function(fn, timer) {
     32             timer.id = setInterval(fn, 16);    // 采用定时器, 时间间隔不能低于16
     33         };
     34     };
     35     if (stopRequest) {
     36         _stopMove = function(timer) {
     37             stopRequest(timer.id);    // 停止动画调用
     38         };
     39     } else {
     40         _stopMove = function(timer) {
     41             clearInterval(timer.id);    // 关闭定时器
     42         };
     43     };
     44 
     45     var Move = function() {};    // Move构造函数
     46 
     47     var curve = Move.prototype = {    // Move原型
     48         extend: function(obj) {
     49             for (var k in obj) {
     50                 if (k in curve) {
     51                     console.warn('扩张的方法名' + k + ': 已经存在, 换个方法名吧!' );
     52                     return;
     53                 };
     54                 curve[k] = (function(moveType) {    // 给Move原型添加 动画曲线 方法
     55                     return function() {
     56                         return _doMove.call(this, arguments, moveType);    // 每个动画曲线方法实际调用_doMove函数
     57                     };
     58                 })(obj[k]);
     59             };
     60         }
     61     };
     62 
     63     /*****  动画曲线  ******/
     64     curve.extend({
     65         //定义域和值域均为[0, 1], 传入自变量x返回对应值y
     66         //先加速后减速
     67         ease: function(x) {
     68             // return -0.5*cos(PI * (2 - x)) + 0.5;
     69             if (x <= 0.5) return 2 * x * x;
     70             else if (x > 0.5) return -2 * x * x + 4 * x - 1;
     71         },
     72 
     73         // 初速度为0 ,一直加速
     74         easeIn: function(x) {
     75             return x * x;
     76         },
     77 
     78         //先慢慢加速1/3, 然后突然大提速, 最后减速
     79         ease2: function(x) {
     80             return x < 1 / 3 ? x * x : -2 * x * x + 4 * x - 1;
     81         },
     82 
     83         //初速度较大, 一直减速, 缓冲动画
     84         easeOut: function(x) {
     85             return pow(x, 0.8);
     86         },
     87 
     88         //碰撞动画
     89         collision: function(x) {
     90             var a, b; //a, b代表碰撞点的横坐标
     91             for (var i = 1, m = 20; i < m; i++) {
     92                 a = 1 - (4 / 3) * pow(0.5, i - 1);
     93                 b = 1 - (4 / 3) * pow(0.5, i);
     94                 if (x >= a && x <= b) {
     95                     return pow(3 * (x - (a + b) / 2), 2) + 1 - pow(0.25, i - 1);
     96                 }
     97             }
     98         },
     99 
    100         //弹性动画
    101         elastic: function(x) {
    102             return -pow(1 / 12, x) * cos(PI * 2.5 * x * x) + 1;
    103         },
    104 
    105         //匀速动画
    106         linear: function(x) {
    107             return x;
    108         },
    109 
    110         //断断续续加速减速
    111         wave: function(x) {
    112             return (1 / 12) * sin(5 * PI * x) + x;
    113         },
    114 
    115         //先向反方向移动一小段距离, 然后正方向移动, 并超过终点一小段, 然后回到终点
    116         opposite: function(x) {
    117             return (sqrt(2) / 2) * sin((3 * PI / 2) * (x - 0.5)) + 0.5;
    118         },
    119 
    120         // 相反的三次贝塞尔
    121         reverseEase: function (x) {    
    122             return 1 - Math.sqrt(1 - x * x);
    123         }
    124     });
    125 
    126     /**
    127      * 开始动画函数
    128      * arg: 用户要传的([0, 1000], 500, function(v){ ... }, fnEnd)
    129      * moveType: 曲线动画函数
    130      */
    131     function _doMove(arg, moveType) {
    132         var r,    // r => 过渡范围, 例如[0, 1000]   (必须传, 且传数组)
    133             d,    // d => 过渡时间, ms,             (可不传, 默认500) 
    134             fn,    // fn => 每一帧的回调函数, 传入当前过渡值v   (必须传) 
    135             fnEnd;    // fnEnd => 动画结束时回调               (可不传)    
    136 
    137         // 严格限制传入参数, 且传入的参数可以没有顺序
    138         for (var i = 0; i < 4; i++) {
    139             if (typeof arg[i] === 'object' && !r) r = arg[i];
    140             else if (typeof arg[i] === 'number' && !d) d = arg[i];
    141             else if (typeof arg[i] === 'function' && !fn) fn = arg[i];
    142             else if (typeof arg[i] === 'function' && !fnEnd) fnEnd = arg[i];
    143         };
    144 
    145         if (!r instanceof Array || !fn) return;    // 如果r不是数组或者fn不是函数(真值)就return掉
    146 
    147         d = d || 500;    // 过渡时间默认500ms
    148 
    149         var from = +new Date, //起始时间
    150             x = 0,    
    151             y,
    152             a = r[0],    // 过渡范围的起点
    153             b = r[1];    // 过度范围的终点
    154 
    155         var timer = 't' + Math.random();    // 随机数
    156 
    157         var self = this;    // 存一下Move的实例
    158 
    159         //用于保存定时器ID的对象, requestAnimation递归调用必须传入对象(给实例添加timer属性值为{})
    160         this[timer] = {};
    161 
    162         // 优先使用requestAnimationFrame否则setInterval定时器
    163         _move(function() {
    164             x = (+new Date - from) / d;
    165 
    166             if (x >= 1) {    // 动画结束
    167                 fn(b);    // 调用外部动画的回调函数且把过度范围的终点值作为参数传过去
    168                 if (fnEnd) fnEnd();    // 如果有动画结束回调函数就执行回调函数
    169                 return true;    // 返回真值停止调用requestAnimationFrame方法
    170             } else {    // 动画进行中
    171                 y = moveType(x);    // 调用动画曲线中的函数返回运动数字
    172                 fn(a + (b - a) * y);    // 调用外部动画的回调函数传参为 a + (b - a) * y
    173             };
    174         }, self[timer]);
    175 
    176         return function() {
    177             _stopMove(self[timer]);    // 调用cancelAnimationFrame方法停止动画
    178             return a + (b - a) * y;    // 返回动画停止后的运动数字
    179         };
    180     };
    181 
    182     // 抛出去
    183     if (typeof module === 'object' && module.exports) {
    184         module.exports = new Move;
    185     } else {
    186         if (window.move) {
    187             try {
    188                 console.warn('move has been declared!');
    189             } catch (e) {};
    190         } else {
    191             window.move = new Move;    // 抛出去的是个Move实例
    192         }
    193     };
    194 }();

    使用姿势:

            var box = document.querySelector("#box");
    
            // 扩展运动函数
            move.extend({
                fast: function(x) {
                    return x * x * x;
                },
                reverseEase: function (x) {    // 相反的三次贝塞尔
                    return 1 - Math.sqrt(1 - x * x);
                }
            })
    
            // 使用姿势
            var stop = move.reverseEase([0, 500], 1000, function(v){
                console.log(v);
                box.style.left = v + 'px';
            }, function(){
                console.log('动画完成');
            });
    
            setTimeout(function() {
                var val = stop();  //停止动画
                console.log('停止:' + val);
            }, 500);

    个人喜好,我改成了自己喜欢的源码,添加了随机取动画名字:

      1 ; (function() {
      2 
      3     var PI = Math.PI,
      4         sin = Math.sin,
      5         cos = Math.cos,
      6         pow = Math.pow,
      7         abs = Math.abs,
      8         sqrt = Math.sqrt;
      9 
     10     var request = window.requestAnimationFrame,
     11         stopRequest = window.cancelAnimationFrame;
     12     var _move, _stopMove;    // 都是函数, 不支持requestAnimationFrame的浏览器就使用定时器
     13 
     14     //初始化运动函数和停止函数  
     15     if (request) {
     16         _move = function(fn, timer) {    // fn: 匿名函数, timer: 不同的空对象
     17             var step = function() {
     18                 if (!fn()) {    // fn函数返回值为假值则调用requestAnimationFrame方法(true代表运动结束)
     19                     timer.id = request(step);
     20                 };
     21             };
     22             step();    // 函数调用
     23         };
     24     } else {
     25         _move = function(fn, timer) {
     26             timer.id = setInterval(fn, 16);    // 采用定时器, 时间间隔不能低于16
     27         };
     28     };
     29     if (stopRequest) {
     30         _stopMove = function(timer) {
     31             stopRequest(timer.id);    // 停止动画调用
     32         };
     33     } else {
     34         _stopMove = function(timer) {
     35             clearInterval(timer.id);    // 关闭定时器
     36         };
     37     };
     38 
     39     var Move = function() {    // Move构造函数
     40         this.aCurve = [];    // 曲线动画函数名集合
     41         this.init();
     42     };    
     43 
     44 
     45     var curve = Move.prototype = {    // Move原型
     46         // 初始化动画曲线 
     47         init: function() {
     48             this.extends({
     49                 //定义域和值域均为[0, 1], 传入自变量x返回对应值y
     50                 //先加速后减速
     51                 ease: function(x) {
     52                     // return -0.5*cos(PI * (2 - x)) + 0.5;
     53                     if (x <= 0.5) return 2 * x * x;
     54                     else if (x > 0.5) return -2 * x * x + 4 * x - 1;
     55                 },
     56 
     57                 // 初速度为0 ,一直加速
     58                 easeIn: function(x) {
     59                     return x * x;
     60                 },
     61 
     62                 //先慢慢加速1/3, 然后突然大提速, 最后减速
     63                 ease2: function(x) {
     64                     return x < 1 / 3 ? x * x : -2 * x * x + 4 * x - 1;
     65                 },
     66 
     67                 //初速度较大, 一直减速, 缓冲动画
     68                 easeOut: function(x) {
     69                     return pow(x, 0.8);
     70                 },
     71 
     72                 //碰撞动画
     73                 collision: function(x) {
     74                     var a, b; //a, b代表碰撞点的横坐标
     75                     for (var i = 1, m = 20; i < m; i++) {
     76                         a = 1 - (4 / 3) * pow(0.5, i - 1);
     77                         b = 1 - (4 / 3) * pow(0.5, i);
     78                         if (x >= a && x <= b) {
     79                             return pow(3 * (x - (a + b) / 2), 2) + 1 - pow(0.25, i - 1);
     80                         }
     81                     }
     82                 },
     83 
     84                 //弹性动画
     85                 elastic: function(x) {
     86                     return -pow(1 / 12, x) * cos(PI * 2.5 * x * x) + 1;
     87                 },
     88 
     89                 //匀速动画
     90                 linear: function(x) {
     91                     return x;
     92                 },
     93 
     94                 //断断续续加速减速
     95                 wave: function(x) {
     96                     return (1 / 12) * sin(5 * PI * x) + x;
     97                 },
     98 
     99                 //先向反方向移动一小段距离, 然后正方向移动, 并超过终点一小段, 然后回到终点
    100                 opposite: function(x) {
    101                     return (sqrt(2) / 2) * sin((3 * PI / 2) * (x - 0.5)) + 0.5;
    102                 },
    103 
    104                 // 相反的三次贝塞尔
    105                 reverseEase: function (x) {    
    106                     return 1 - Math.sqrt(1 - x * x);
    107                 }
    108             });
    109         },
    110 
    111         // 随机选择一个动画方法名
    112         getRd: function () {
    113             var preItem = null;
    114 
    115             return function () {
    116                 var arr = this.aCurve;
    117                 var index = Math.floor(Math.random() * arr.length),
    118                     item = arr[index],
    119                     result;
    120 
    121                 if (preItem != item) {
    122                     preItem = item;
    123                     result = item;
    124                 } else {
    125                     result = this.getRd(arr);
    126                 };
    127 
    128                 return result;
    129             };
    130         }(),
    131 
    132         // 扩张曲线动画
    133         extends: function(obj) {
    134             for (var k in obj) {
    135                 if (k in curve) {
    136                     console.warn('扩张的方法名' + k + ': 已经存在, 换个方法名吧!' );
    137                     return;
    138                 };
    139                 this.aCurve.push(k);
    140                 curve[k] = (function(moveType) {    // 给Move原型添加 动画曲线 方法
    141                     return function() {
    142                         return _doMove.call(this, arguments, moveType);    // 每个动画曲线方法实际调用_doMove函数
    143                     };
    144                 })(obj[k]);
    145             };
    146         }
    147     };
    148 
    149 
    150     /**
    151      * 开始动画函数
    152      * arg: 用户要传的([0, 1000], 500, function(v){ ... }, fnEnd)
    153      * moveType: 曲线动画函数
    154      */
    155     function _doMove(arg, moveType) {
    156         var r,    // r => 过渡范围, 例如[0, 1000]   (必须传, 且传数组)
    157             d,    // d => 过渡时间, ms,             (可不传, 默认500) 
    158             fn,    // fn => 每一帧的回调函数, 传入当前过渡值v   (必须传) 
    159             fnEnd;    // fnEnd => 动画结束时回调               (可不传)    
    160 
    161         // 严格限制传入参数, 且传入的参数可以没有顺序
    162         for (var i = 0; i < 4; i++) {
    163             if (typeof arg[i] === 'object' && !r) r = arg[i];
    164             else if (typeof arg[i] === 'number' && !d) d = arg[i];
    165             else if (typeof arg[i] === 'function' && !fn) fn = arg[i];
    166             else if (typeof arg[i] === 'function' && !fnEnd) fnEnd = arg[i];
    167         };
    168 
    169         if (!r instanceof Array || !fn) return;    // 如果r不是数组或者fn不是函数(真值)就return掉
    170 
    171         d = d || 500;    // 过渡时间默认500ms
    172 
    173         var from = +new Date, //起始时间
    174             x = 0,    
    175             y,
    176             a = r[0],    // 过渡范围的起点
    177             b = r[1];    // 过度范围的终点
    178 
    179         var timer = 't' + Math.random();    // 随机数
    180 
    181         var self = this;    // 存一下Move的实例
    182 
    183         //用于保存定时器ID的对象, requestAnimation递归调用必须传入对象(给实例添加timer属性值为{})
    184         this[timer] = {};
    185 
    186         // 优先使用requestAnimationFrame否则setInterval定时器
    187         _move(function() {
    188             x = (+new Date - from) / d;
    189 
    190             if (x >= 1) {    // 动画结束
    191                 fn(b);    // 调用外部动画的回调函数且把过度范围的终点值作为参数传过去
    192                 if (fnEnd) fnEnd();    // 如果有动画结束回调函数就执行回调函数
    193                 return true;    // 返回真值停止调用requestAnimationFrame方法
    194             } else {    // 动画进行中
    195                 y = moveType(x);    // 调用动画曲线中的函数返回运动数字
    196                 fn(a + (b - a) * y);    // 调用外部动画的回调函数传参为 a + (b - a) * y
    197             };
    198         }, self[timer]);
    199 
    200         return function() {
    201             _stopMove(self[timer]);    // 调用cancelAnimationFrame方法停止动画
    202             return a + (b - a) * y;    // 返回动画停止后的运动数字
    203         };
    204     };
    205 
    206     // 抛出去
    207     if (typeof module === 'object' && module.exports) {
    208         module.exports = Move;
    209     } else {
    210         if (window.Move) {
    211             try {
    212                 console.warn('Move has been declared!');
    213             } catch (e) {};
    214         } else {
    215             window.Move = Move;    // Move构造函数抛出去
    216         }
    217     };
    218 })();

    使用姿势:

            var move = new Move();
            
            move.extends({    // 自己自定义扩展
                fast: function(x) {
                    return x * x * x;
                },
                reverseEase: function (x) {    // 相反的三次贝塞尔
                    return 1 - Math.sqrt(1 - x * x);
                }
            })
    
            document.querySelector('#btn').addEventListener('click', function() {
                // 使用姿势
                var rd = move.getRd();
                var stop = move[rd]([0, 500], 1000, function(v){
                    console.log(v);
                    box.style.left = v + 'px';
                }, function(){
                    console.log('动画完成');
                });
    
                setTimeout(function() {
                    var val = stop();  //停止动画
                    console.log('停止:' + val);
                }, 500);
            }, false);

    ps:

         很喜欢的一个数字运动小型库,便于扩张各种运动。配合dnt的transform.js,真的很不错。

         很多ios和安卓的前端动画都能轻松写出来。

         比jq提供的动画更加强大和灵活。

         我只是个搬运工,喜欢的库自然会贴出原作者地址。

         看原作者怎么说明的:https://github.com/flfwzgl/move

    开心的做一个无忧无虑的码农,争取每天进步一点。
  • 相关阅读:
    泛微云桥e-Bridge 目录遍历,任意文件读取
    (CVE-2020-8209)XenMobile-控制台存在任意文件读取漏洞
    selenium 使用初
    将HTML文件转换为MD文件
    Python对word文档进行操作
    使用java安装jar包出错,提示不是有效的JDK java主目录
    Windows server 2012安装VM tools异常解决办法
    ifconfig 命令,改变主机名,改DNS hosts、关闭selinux firewalld netfilter 、防火墙iptables规则
    iostat iotop 查看硬盘的读写、 free 查看内存的命令 、netstat 命令查看网络、tcpdump 命令
    使用w uptime vmstat top sar nload 等命令查看系统负载
  • 原文地址:https://www.cnblogs.com/sorrowx/p/6490410.html
Copyright © 2011-2022 走看看