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

时间:2023-03-09 08:27:32
JS特效@缓动框架封装及应用
| 版权声明:本文为博主原创文章,未经博主允许不得转载。

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

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

1)div.style.width

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

2)div.style[“width”]

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

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

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

1)w3c:window.getComputedStyle(元素,伪元素)["left"]

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

2)IE:div.currentStyle.left或 div.current["left"]

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

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

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

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

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

 btnArr[0].onclick = function () {
//以对象键值对的形式传参
var json = {"left":10,"top":200,"width":300,"height":200};
animate(div,json);
} function animate(ele,json){
//json{属性名:属性值}{attr:target}
//先清定时器
clearInterval(ele.timer);
ele.timer = setInterval(function () {
//遍历属性和值,分别单独处理json
//attr == k(键) target == json[k](值)
for(var k in json){
var leader = parseInt(getStyle(ele,k)) || 0;
//1.获取步长
var step = (json[k] - leader)/10;
//2.二次加工步长
step = step>0?Math.ceil(step):Math.floor(step);
leader = leader + step;
//3.赋值
ele.style[k] = leader + "px"; }
},25);
} //兼容方法获取元素样式
function getStyle(ele,attr){
if(window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}
return ele.currentStyle[attr];
}

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

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

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

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

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

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

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

4)回调函数的例子

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

 简单案例代码:
//定义主函数,回调函数作为参数
function A(callback) {
callback();
console.log('我是主函数');
}
//定义回调函数
function B(){
setTimeout("console.log('我是回调函数')", 3000);//模仿耗时操作 }
//调用主函数,将函数B传进去
A(B); //输出结果
我是主函数
我是回调函数

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

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

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

 btnArr[0].onclick = function () {
var json1 = {"left":300,"top":200,"width":300,"height":200};
var json2 = {"left":10,"top":30,"width":100,"height":100};
//回调函数放在主函数里面
animate(div,json1, function () {
animate(div,json2, function () {
animate(div,json1);
});
}); } function animate(ele,json,fn){
//先清定时器
clearInterval(ele.timer);
ele.timer = setInterval(function () {
//开闭原则,假设这一次执行完成后,所有的属性都能达到目标值
var bool = true; //遍历属性和值,分别单独处理json
//attr == k(键) target == json[k](值)
for(var k in json){
//四步
var leader = parseInt(getStyle(ele,k)) || 0;
//1.获取步长
var step = (json[k] - leader)/10;
//2.二次加工步长
step = step>0?Math.ceil(step):Math.floor(step);
leader = leader + step;
//3.赋值
ele.style[k] = leader + "px";
//4.清除定时器
//判断: 目标值和当前值的差大于步长,就不能跳出循环
//不考虑小数的情况:目标位置和当前位置不相等,就不能清除清除定时器。
if(json[k] !== leader){//当前这个属性还没有达到目标值
bool = false;
}
}
//只有所有的属性都到了指定位置,bool值才不会变成false;
if(bool){//如果此时仍然是true说明所有的都到目标了
clearInterval(ele.timer);
//所有程序执行完毕了,现在可以执行回调函数了
//只有传递了回调函数,才能执行,就是说如果fn存在,就执行fn这个方法;
if(fn){
fn();
}
}//动画完成之后执行
},25);
} //兼容方法获取元素样式
function getStyle(ele,attr){
if(window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}
return ele.currentStyle[attr];
}

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

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

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

 <script src="../01.js"></script>
<script>
window.onload = function () {
//步骤:
//1.给li添加背景
//2.绑定onmouseover事件,鼠标放入到li中该盒子变宽,其他的盒子变窄
//3.移开大盒子,回复原样 var div = document.getElementsByTagName("div")[0];
var liArr = div.getElementsByTagName("li");
//1.给li添加背景
for(var i=0;i<liArr.length;i++){
liArr[i].style.background = "url(images/"+(i+1)+".jpg) no-repeat"; //2.绑定onmouseover事件,鼠标放入到li中该盒子变宽,其他的盒子变窄
liArr[i].onmouseover = function () {
//排他思想
for(var j=0;j<liArr.length;j++){
//引用框架实现宽度变窄
animate(liArr[j],{"width":100});
}
//剩下他自己
animate(this,{"width":800})
}
} //3.移开大盒子,回复原样
div.onmouseout = function () {
for(var j=0;j<liArr.length;j++){
//引用框架实现宽度变窄
animate(liArr[j],{"width":240});
}
}
}
</script>

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

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

 <!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box{
width: 322px;
position: fixed;
bottom:0;
right:0;
}
span{
position: absolute;
top:0;
right:0;
width:30px;
height: 20px;
cursor: pointer;
}
</style>
<script src="../jquery1.0.0.1.js"></script>
<script>
window.onload = function () {
//需求:下面的盒子高度变为0,然后大盒子的宽在变为0.
var guanbi = document.getElementById("guanbi");
var box = guanbi.parentNode;
var b = document.getElementById("b"); guanbi.onclick = function () {
//下面的盒子高度变为0,然后大盒子的宽在变为0.
animate(b,{"height":0}, function () {
animate(box,{"width":0});
});
}
}
</script>
</head>
<body>
<div class="box">
<span id="guanbi"></span>
<div class="hd" id="t">
<img src="data:images/t.jpg" alt=""/>
</div>
<div class="bd" id="b">
<img src="data:images/b.jpg" alt=""/>
</div>
</div>
</body>
</html>