JS特效@缓动框架封装及应用

Posted 泳少爷--前端攻城狮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS特效@缓动框架封装及应用相关的知识,希望对你有一定的参考价值。

| 版权声明:本文为博主原创文章,未经博主允许不得转载。

一、变量CSS样式属性获取/赋值方法

给属性赋值:(既能获取又能赋值)

1div.style.width    

单个赋值:点语法,这个方法比较固定,不能用变量或者字符串的形式更换属性,不方便我们传值获取属性,和给属性赋值

2div.style[width]    

变量赋值:中括号形式,传入字符串。可以通过传字符串或者变量的方式获取和赋值属性。缺点:只能是对行内式CSS来操作的赋值的时候毫无问题。但是,获取值的时候有问题了。

 

二、封装获取样式属性值的兼容方法

工作中我们经常需要获取一个盒子的最终样式比如要获取未加定位的盒子的left属性值那么如何到计算后的样式属性值呢:

1)w3cwindow.getComputedStyle(元素,伪元素)["left"]

第二个参数是伪元素,我们传入null即可

2IEdiv.currentStyle.leftdiv.current["left"]

//兼容方法获取元素样式ele为元素,attr为属性

1 //兼容方法获取元素样式(ele为元素,attr为属性)
2 function getStyle(ele,attr){
3   if(window.getComputedStyle){
4      return window.getComputedStyle(ele,null)[attr];
5    }
6      return ele.currentStyle[attr];
7                      }

 

三、封装缓动框架(单个数值属性)

 1 //参数变为3个,封装能够让任意对象的指定属性变到指定值的动画函数
 2 function animate(ele,attr,target){
 3             //先清定时器
 4             clearInterval(ele.timer);
 5             ele.timer = setInterval(function () {
 6             var leader = parseInt(getStyle(ele,attr)) || 0;  //获取任意样式属性。
 7                 //1.获取步长
 8                 var step = (target - leader)/10;
 9                 //2.二次加工步长
10                 step = step>0?Math.ceil(step):Math.floor(step);
11                 leader = leader + step;
12                 //ele.style.left=leader+"px";
13                 //原来的方式只能设置left
14                 //3.赋值,可以设置任意属性
15                 ele.style[attr] = leader + "px";
16                  //4.清除定时器
17                 if(Math.abs(target-leader)<=Math.abs(step)){
18                     ele.style[attr] = target + "px";
19                     clearInterval(ele.timer);
20                 }
21 
22             },25);
23         }
24 
25  //兼容方法获取元素样式  
26 function getStyle(ele,attr){
27             if(window.getComputedStyle){
28                 return window.getComputedStyle(ele,null)[attr];
29             }
30             return ele.currentStyle[attr];
31         }

 

四、封装缓动框架(多个数值属性)

 1 btnArr[0].onclick = function () {
 2             //以对象键值对的形式传参
 3             var json = {"left":10,"top":200,"width":300,"height":200};
 4             animate(div,json);
 5         }
 6 
 7 function animate(ele,json){ 
 8             //json{属性名:属性值}{attr:target}
 9             //先清定时器
10             clearInterval(ele.timer);
11             ele.timer = setInterval(function () {
12                 //遍历属性和值,分别单独处理json
13                 //attr == k(键)    target == json[k](值)
14                 for(var k in json){
15                     var leader = parseInt(getStyle(ele,k)) || 0;
16                     //1.获取步长
17                     var step = (json[k] - leader)/10;
18                     //2.二次加工步长
19                     step = step>0?Math.ceil(step):Math.floor(step);
20                     leader = leader + step;
21                     //3.赋值
22                     ele.style[k] = leader + "px";
23                 
24                 }
25             },25);
26         }
27 
28 //兼容方法获取元素样式
29 function getStyle(ele,attr){
30             if(window.getComputedStyle){
31                 return window.getComputedStyle(ele,null)[attr];
32             }
33             return ele.currentStyle[attr];
34         }

 

五、封装缓动框架(清除定时器

 1 btnArr[0].onclick = function () {
 2             var json = {"left":10,"top":200,"width":300,"height":200};
 3             animate(div,json);
 4         }
 5 
 6 function animate(ele,json){
 7             //先清定时器
 8             clearInterval(ele.timer);
 9             ele.timer = setInterval(function () {
10                 //开闭原则
11                 var bool = true;
12 
13                 //遍历属性和值,分别单独处理json
14                 //attr == k(键)    target == json[k](值)
15                 for(var k in json){
16                     //四步
17                     var leader = parseInt(getStyle(ele,k)) || 0;
18                     //1.获取步长
19                     var step = (json[k] - leader)/10;
20                     //2.二次加工步长
21                     step = step>0?Math.ceil(step):Math.floor(step);
22                     leader = leader + step;
23                     //3.赋值
24                     ele.style[k] = leader + "px";
25                    //4.清除定时器
26      //判断: 目标值和当前值的差大于步长,就不能跳出循环
27      //不考虑小数的情况:目标位置和当前位置不相等,就不能清除清除定时器。
28                     if(json[k] !== leader){//当前这个属性还没有达到目标值
29                         bool = false;
30                     }
31                 }
32 
33               //只有所有的属性都到了指定位置,bool值才不会变成false;
34                 if(bool){//如果此时仍然是true说明所有的都到目标了
35                     clearInterval(ele.timer);
36                 }
37             },25);
38         }
39 
40 
41 
42 
43  //兼容方法获取元素样式
44  function getStyle(ele,attr){
45             if(window.getComputedStyle){
46                 return window.getComputedStyle(ele,null)[attr];
47             }
48             return ele.currentStyle[attr];
49         }

 

六、封装缓动框架(添加回调函数

首先弄清楚什么是回调函数,回调函数B就是一个参数,将这个函数作为参数传到主函数A里面,当主函数A执行完之后,再执行传进去的这个函数B。这个过程就叫做回调。回调,就是回头调用的意思。主函数的事先干完,回头再调用传进来的那个函数。

1)回调函数怎么起作用?
把我要执行的这个任务写成一个函数,将这个函数和某一时间或者事件或者中断建立关联。当这个关联完成的时候,这个函数华丽的从普通函数变身成为回调函数。

2)回调函数什么时候执行?
当该回调函数关心的那个时间或者事件或者中断触发的时候,回调函数将被执行。
一般是触发这个时间、事件或中断的程序主体(通常是个函数或者对象)观察到有一个关注这个东东的回调函数的时候,这个主体负责调用这个回调函数。

3)回调函数有什么好处?
最大的好处是你的程序变成异步了。也就是你不必再调用这个函数的时候一直等待这个时间的到达、事件的发生或中断的发生(万一一直不发生,你的程序会怎么样?)。再此期间你可以做做别的事情,或者四处逛逛。当回调函数被执行时,你的程序重新得到执行的机会,此时你可以继续做必要的事情了。

4)回调函数的例子

约会结束后你送你女朋友回家,离别时,你肯定会说:到家了给我发条信息,我很担心你。对不,然后你女朋友回家以后还真给你发了条信息。小伙子,你有戏了。其实这就是一个回调的过程。你留了个参数函数(要求女朋友给你发条信息)给你女朋友, 然后你女朋友回家,回家的动作是主函数。她必须先回到家以后,主函数执行完了,再执行传进去的函数,然后你就收到一条信息了。

 1 简单案例代码:
 2 //定义主函数,回调函数作为参数
 3 function A(callback) {
 4     callback();  
 5     console.log(\'我是主函数\');      
 6 }
 7 //定义回调函数
 8 function B(){
 9     setTimeout("console.log(\'我是回调函数\')", 3000);//模仿耗时操作  }
10 //调用主函数,将函数B传进去
11 A(B);
12 
13 //输出结果
14 我是主函数
15 我是回调函数

 

上面的代码中,我们先定义了主函数和回调函数,然后再去调用主函数,将回调函数传进去。

定义主函数的时候,我们让代码先去执行callback()回调函数,但输出结果却是后输出回调函数的内容。这就说明了主函数不用等待回调函数执行完,可以接着执行自己的代码。所以一般回调函数都用在耗时操作上面。比如ajax请求,比如处理文件等。

 

介绍完回调函数后,我们回到封装缓动框架这个问题上,假如我想让某个盒子运动出去后再运动回来,运用传统的思路写两个函数并列,后面的函数会覆盖前面的函数。那么我们就需要用到回调函数。我们先让盒子运动出去(主函数,这个函数加入了回调函数这个参数),当运动出去后,让它运动回来(执行回调函数)。

 1 btnArr[0].onclick = function () {
 2             var json1 = {"left":300,"top":200,"width":300,"height":200};
 3             var json2 = {"left":10,"top":30,"width":100,"height":100};
 4             //回调函数放在主函数里面
 5             animate(div,json1, function () {
 6                 animate(div,json2, function () {
 7                     animate(div,json1);
 8                 });
 9             });
10      
11         }
12 
13 function animate(ele,json,fn){
14             //先清定时器
15             clearInterval(ele.timer);
16             ele.timer = setInterval(function () {
17            //开闭原则,假设这一次执行完成后,所有的属性都能达到目标值
18                 var bool = true;
19 
20 
21                 //遍历属性和值,分别单独处理json
22                 //attr == k(键)    target == json[k](值)
23                 for(var k in json){
24                     //四步
25                     var leader = parseInt(getStyle(ele,k)) || 0;
26                     //1.获取步长
27                     var step = (json[k] - leader)/10;
28                     //2.二次加工步长
29                     step = step>0?Math.ceil(step):Math.floor(step);
30                     leader = leader + step;
31                     //3.赋值
32                     ele.style[k] = leader + "px";
33                     //4.清除定时器
34       //判断: 目标值和当前值的差大于步长,就不能跳出循环
35     //不考虑小数的情况:目标位置和当前位置不相等,就不能清除清除定时器。
36                     if(json[k] !== leader){//当前这个属性还没有达到目标值
37                         bool = false;
38                     }
39                 }
40           //只有所有的属性都到了指定位置,bool值才不会变成false;
41                 if(bool){//如果此时仍然是true说明所有的都到目标了
42                     clearInterval(ele.timer);
43       //所有程序执行完毕了,现在可以执行回调函数了
44     //只有传递了回调函数,才能执行,就是说如果fn存在,就执行fn这个方法;
45                     if(fn){
46                         fn();
47                     }
48                 }//动画完成之后执行
49             },25);
50         }
51 
52 
53  //兼容方法获取元素样式
54  function getStyle(ele,attr){
55             if(window.getComputedStyle){
56                 return window.getComputedStyle(ele,null)[attr];
57             }
58             return ele.currentStyle[attr];
59         }

 

七、封装缓动框架(手风琴案例)

需求:鼠标放入到li中该盒子变宽,其他的盒子变窄。移开大盒子,回复原样。

 

 1 <script src="../01.js"></script>
 2     <script>
 3         window.onload = function () {
 4             //步骤:
 5       //1.给li添加背景
 6       //2.绑定onmouseover事件,鼠标放入到li中该盒子变宽,其他的盒子变窄
 7       //3.移开大盒子,回复原样
 8 
 9             var div = document.getElementsByTagName("div")[0];
10             var liArr = div.getElementsByTagName("li");
11             //1.给li添加背景
12             for(var i=0;i<liArr.length;i++){
13                 liArr[i].style.background = "url(images/"+(i+1)+".jpg) no-repeat";
14 
15     //2.绑定onmouseover事件,鼠标放入到li中该盒子变宽,其他的盒子变窄
16                 liArr[i].onmouseover = function () {
17                     //排他思想
18                     for(var j=0;j<liArr.length;j++){
19                         //引用框架实现宽度变窄
20                         animate(liArr[j],{"width":100});
21                     }
22                     //剩下他自己
23                        animate(this,{"width":800})
24                 }
25             }
26 
27             //3.移开大盒子,回复原样
28             div.onmouseout = function () {
29                 for(var j=0;j<liArr.length;j++){
30                     //引用框架实现宽度变窄
31                     animate(liArr[j],{"width":240});
32                 }
33             }
34         }
35     </script>

 

八、封装缓动框架(关闭360动画特效

 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title></title>
 6     <style>
 7         .box{
 8             width: 322px;
 9             position: fixed;
10             bottom:0;
11             right:0;
12         }
13         span{
14             position: absolute;
15             top:0;
16             right:0;
17             width:30px;
18             height: 20px;
19             cursor: pointer;
20         }
21     </style>
22     <script src="../jquery1.0.0.1.js"></script>
23     <script>
24         window.onload = function () {
25             //需求:下面的盒子高度变为0,然后大盒子的宽在变为0.
26             var guanbi = document.getElementById("guanbi");
27             var box = guanbi.parentNode;
28             var b = document.getElementById("b");
29 
30             guanbi.onclick = function () {
31                 //下面的盒子高度变为0,然后大盒子的宽在变为0.
32                 animate(b,{"height":0}, function () {
33                     animate(box,{"width":0});
34                 });
35             }
36         }
37     </script>
38 </head>
39 <body>
40     <div class="box">
41         <span id="guanbi"></span>
42         <div class="hd" id="t">
43             <img src="images/t.jpg" alt=""/>
44         </div>
45         <div class="bd" id="b">
46             <img src="images/b.jpg" alt=""/>
47         </div>
48     </div>
49 </body>
50 </html>

 

 

 

 

 

 

 

 

以上是关于JS特效@缓动框架封装及应用的主要内容,如果未能解决你的问题,请参考以下文章

tween 缓动动画

利用tween.js算法生成缓动效果

jQuery特效 | 导航底部横线跟随鼠标缓动

JavaScript——WEBAPIS_深入动画函数的封装,常见网页特效

回归 | js实用代码片段的封装与总结(持续更新中...)

JS---封装缓动(变速)动画函数---增加任意多个属性&增加回调函数