• 一个原生JavaScript动画库原型


    设计目标:简单易用,不依赖其他库,对旧版浏览器具有一定兼容性,功能可扩展。

    动画调用:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>为若干个标签添加若干个动画,动画要有变化属性(默认为样式属性)、动画名、属性值类型、是否循环、多关键帧、ease函数(默认为线性)、有添加方法、删除方法</title>
     6     <style>
     7         .div_ani {background: red;width: 100px;height:100px;position:relative}
     8     </style>
     9     <script src="Ani.js"></script>
    10 </head>
    11 <body>
    12     <div class="div_ani">111</div>
    13     <div class="div_ani">222</div>
    14 </body>
    15 <!--script type="module"-->
    16 <script>
    17     //import Ani from './ani.js'
    18     let objs1=document.querySelector(".div_ani");
    19     let objs2=document.querySelectorAll(".div_ani");
    20     Ani.addAni(objs2,[
    21     {
    22       arr_pname:"width",loop:true,endcallback:function(){console.log("动画结束")}//动画属性
    23       ,arr_key:[//关键帧数组
    24         {ms:0,value:100,callback:function(ani){console.log(ani.elem.innerHTML+"第0ms")}},
    25         {ms:1000,value:300,callback:function(){console.log("第1000ms")}},
    26         {ms:2000,value:100,callback:function(){console.log("第2000ms")}},
    27       ]
    28     }
    29   ]//addAni的第一个参数可以是dom对象或dom对象数组,第二个参数是动画对象数组
    30     )
    31   //可以多次执行addAni添加更多动画
    32     Ani.startAni();//启动所有动画
    33     
    34 
    35 
    36 
    37     
    38 </script>
    39 </html>

    代码实现:

      1 //考虑到更好的兼容性
      2 // export default class Ani{
      3 //     constructor(elem,p){
      4 //         /*let p_default={
      5 //             type:"css_px",
      6 //             id:Ani.randomString(32),//没有必要生成两次
      7 //
      8 //         }*/
      9 //         this.type=p.type||"css_px";
     10 //         this.id=p.id||Ani.randomString(32);
     11 //         this.arr_key=[];
     12 //         let len=p.arr_key.length;//每个基础类型属性都要用直接量赋值
     13 //         for(let i=0;i<len;i++)
     14 //         {
     15 //             let key=p.arr_key[i]
     16 //             this.arr_key.push(
     17 //                 {
     18 //                     ms:key.ms,
     19 //                     value:JSON.parse(JSON.stringify(key.value)),
     20 //                     callback:key.callback,//回调函数可以共用一个
     21 //                 }
     22 //             )
     23 //         }
     24 //         //this.arr_key=p.arr_key;
     25 //         this.loop=p.loop;
     26 //         this.elem=elem;
     27 //         this.countms=0;
     28 //         this.arr_pname=p.arr_pname;
     29 //         this.func_ease=p.func_ease||Ani.obj_func_ease.float_line;
     30 //         //this.arr_framecallback=p.arr_framecallback||[];
     31 //         this.endcallback=p.endcallback;
     32 //         this.func_set=p.func_set||Ani.setValue;
     33 //     }
     34 // }
     35 function Ani(elem,p){
     36     this.type=p.type||"css_px";
     37     this.id=p.id||Ani.randomString(32);
     38     this.arr_key=[];
     39     var len=p.arr_key.length;//每个基础类型属性都要用直接量赋值
     40     for(var i=0;i<len;i++)
     41     {
     42         var key=p.arr_key[i]
     43         this.arr_key.push(
     44             {
     45                 ms:key.ms,
     46                 value:JSON.parse(JSON.stringify(key.value)),
     47                 callback:key.callback,//回调函数可以共用一个
     48             }
     49         )
     50     }
     51     //this.arr_key=p.arr_key;
     52     this.loop=p.loop;
     53     this.elem=elem;
     54     this.countms=0;
     55     this.arr_pname=p.arr_pname;
     56     this.func_ease=p.func_ease||Ani.obj_func_ease.float_line;
     57     //this.arr_framecallback=p.arr_framecallback||[];
     58     this.endcallback=p.endcallback;
     59     this.func_set=p.func_set||Ani.setValue;
     60 }
     61 Ani.obj_anis={};
     62 Ani.addAni=function(objs,p_anis)//添加动画
     63 {
     64     if(objs.outerHTML)//如果是一个html标签
     65     {
     66         objs=[objs];
     67     }
     68     var len1=objs.length;
     69     var len2=p_anis.length;
     70     for(var i=0;i<len1;i++)
     71     {
     72         var obj=objs[i];
     73         /*if(!obj.arr_ani)//如果以前没有动画数组,dom元素没有易于使用的唯一id,所以不应把动画配置保存再dom元素对象里
     74         //使用一个全局obj_anis保存所有动画对象
     75         {
     76             obj.arr_ani=[];
     77         }*/
     78         for(var j=0;j<len2;j++)
     79         {
     80             var p_ani=p_anis[j];
     81             var ani=new Ani(obj,p_ani);
     82             Ani.obj_anis[ani.id]=ani;
     83             //let len3=obj.arr_ani;
     84             /*let flag_canpush=true;
     85             for(let k=0;k<len3;k++)
     86             {
     87                 //if(obj.arr_ani[k]===ani)//如果已经添加过这个动画对象
     88                 if(obj.arr_ani[k].id==p_ani.id)
     89                 {
     90                     flag_canpush=false;
     91                 }
     92             }
     93             if(flag_canpush==true)
     94             {
     95                 obj.arr_ani.push(p_ani);
     96             }*/
     97         }
     98 
     99     }
    100 }
    101 Ani.runningAni=false;
    102 
    103 //这里的一个问题是dom元素可能没有唯一id,后面很难再找到它的对象-》使用一个公用对象?
    104 Ani.startAni=function()
    105 {
    106     if(Ani.runningAni==false)
    107     {
    108         Ani.lastframe=new Date().getTime();
    109         //Ani.currentframe=Ani.lastframe;
    110         window.requestAnimFrame(function(){
    111             Ani.Frame();
    112         })
    113     }
    114     Ani.runningAni=true;
    115 }
    116 Ani.pauseAni=function()
    117 {
    118     Ani.runningAni=false;
    119 }
    120 
    121 Ani.Frame=function()
    122 {
    123     Ani.currentframe=new Date().getTime();
    124     Ani.framems=Ani.currentframe-Ani.lastframe;
    125 
    126     //key_called=null;
    127     for(var key in Ani.obj_anis)
    128     {
    129         var ani=Ani.obj_anis[key];
    130         ani.countms+=Ani.framems;
    131         var len=ani.arr_key.length;
    132         var value=null;
    133         for(var i=0;i<len-1;i++)
    134         {
    135             var key1=ani.arr_key[i];
    136             var key2=ani.arr_key[i+1];
    137             if(ani.countms>=key1.ms&&ani.countms<=key2.ms)
    138             {
    139                 value=ani.func_ease(key1,key2,ani.countms);
    140                 //Ani.setValue(ani.elem,value,ani.type,ani.arr_pname);
    141                 ani.func_set(ani.elem,value,ani.type,ani.arr_pname);
    142                 if(key1.callback&&!key1.called)//如果这个关键帧上有回调函数,并且这个帧没有被调用过
    143                 {
    144                     key1.callback(ani);
    145                     key1.called=true;//多个动画时有多个key1,要分别标记
    146                 }
    147                 break;
    148             }
    149         }
    150         var endKey=ani.arr_key[len-1];
    151         if(ani.countms>endKey.ms)//如果完成了一次动画
    152         {
    153             //Ani.setValue(ani.elem,endKey.value,ani.type,ani.arr_pname);
    154             ani.func_set(ani.elem,value,ani.type,ani.arr_pname);
    155             if(endKey.callback)//如果结束帧上有回调函数
    156             {
    157                 endKey.callback();
    158                 console.log(ani.countms);
    159             }
    160             if(ani.loop)
    161             {
    162                 ani.countms=ani.countms%endKey.ms;
    163                 for(var i=0;i<len;i++)
    164                 {
    165                     var key1=ani.arr_key[i];
    166                     key1.called=false;
    167                 }
    168                 
    169             }
    170             else{
    171                 if(ani.endcallback)//如果有动画结束回调
    172                 {
    173                     ani.endcallback(ani);
    174                 }
    175                 
    176                 delete Ani.obj_anis[key];
    177                 ani=null;
    178             }
    179         }
    180 
    181     }
    182     
    183 
    184     Ani.lastframe=Ani.currentframe;
    185     if(Ani.runningAni==true)
    186     {
    187         window.requestAnimFrame(function(){
    188             Ani.Frame();
    189         })
    190     }
    191 }
    192 
    193 
    194 Ani.setValue=function(elem,value,type,arr_pname)//在这里扩展更多的属性设置方法
    195 {
    196     if(type=="css_px")//这时arr_pname只有一层,是一个字符串,处理颜色时则可能是3维数组
    197     {
    198         elem.style[arr_pname]=value+"px";
    199     }
    200     else if(type=="transform-rotate-deg")//
    201     {
    202         elem.style["transform"]="rotate("+value+"deg)";
    203     }
    204 }
    205 Ani.obj_func_ease={//在这里扩展更多的插值方法
    206     //单浮点数线性
    207     float_line:function(key1,key2,countms){
    208         var ms1=key1.ms;
    209         var ms2=key2.ms;
    210         var v1=key1.value;
    211         var v2=key2.value
    212         return Ani.inBetween(ms1,ms2,v1,v2,countms);
    213     }
    214 };
    215 //插值
    216 Ani.inBetween=function(ms1,ms2,v1,v2,ms)
    217 {
    218     var v=v1+((ms-ms1)/(ms2-ms1))*(v2-v1);
    219     return v;
    220 }
    221 Ani.randomString=function(len)
    222 {
    223     len = len || 32;
    224     var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';    /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
    225     var maxPos = $chars.length;
    226     var pwd = '';
    227     for (var i = 0; i < len; i++) {
    228         pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
    229     }
    230     return pwd;
    231 }
    232 
    233 // Copyright 2010, Google Inc.
    234     window.requestAnimFrame = (function() {
    235         return window.requestAnimationFrame ||
    236             window.webkitRequestAnimationFrame ||
    237             window.mozRequestAnimationFrame ||
    238             window.oRequestAnimationFrame ||
    239             window.msRequestAnimationFrame ||
    240             function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
    241                 window.setTimeout(callback, 1000/60);
    242             };
    243     })();

    编写过程中参考了Babylon.js动画模块、Google requestAnimFrame方法、网上的randomString方法。可基于MIT协议发布的部分基于MIT协议发布,项目Github地址:https://github.com/ljzc002/SimpleAni。

  • 相关阅读:
    nginx限制某个IP同一时间段的访问次数
    在64位机器上使用yum install特定指定安装32位的库
    pl sql developer连接oracle数据库提示:ORA12541: TNS: no listener
    [转]Eclipse中几种加入包方式的区别
    Oracle安装出现Can't connect to X11 window
    [转]ORACLE10GR2,dbca时ora27125错误解决方法
    [转]教你如何进入google国际版 不跳转g.cn 及 opendns
    安装oracle遇到的故障
    [转]宝文!Apple Push Notification Service (APNS)原理与实现方案
    [转]关于安卓与ios的推送系统,我说说自己的看法。
  • 原文地址:https://www.cnblogs.com/ljzc002/p/13896348.html
Copyright © 2020-2023  润新知