先来说说外链式的js的使用方式
<script type="text/javascript" src="animate.js"></script>这就是我们外链式的使用方法。
animate.js包含了我们动画运动框架的方法。
运动框架的编写
动画什么来的,在指定的时间内,通过定时器去不断的改变属性。
所以我们需要写一个animate方法,那么需要传入对象,属性,时间三个参数。
// 封装运动函数
function animate(obj,endJson,time) {
var start_list = {};//参数原始数据
var change_list = {};//需要改变的值
var change_now_list = {};//改变后的值
var interval = 50;//频率
var timers = time/interval;//改变总次数
for(var k in endJson){
start_list[k] = parseInt(fetchComputedStyle(obj,k));//获取到所需要改变属性目前的值
change_now_list[k] = parseInt(fetchComputedStyle(obj,k));//每个属性改变后的值
}
for(var k in start_list){
change_list[k] = (endJson[k]-start_list[k])/timers;//每个属性需要改变的值
}
var count = 0;
var timer = setInterval(function(){
for(var k in start_list){//设置定时器,让个个属性自增
change_now_list[k] += change_list[k];
obj.style[k] = change_now_list[k]+"px";//改变属性的值,从而形成动画
}
count++;
if (count==timers) {//达到改变次数的最大值得时候,取消定时器
clearInterval(timer);
}
},interval);
}
// 定义函数
function fetchComputedStyle(obj,property) {//能力检查,获取计算后属性
if(window.getComputedStyle) {
return getComputedStyle(obj)[property];
} else {
property = property.replace(/\-([a-z])/g,function(match,$1) {
return $1.substring(1,2).toUpperCase();
});
return obj.currentStyle[property];
}
}
以上就是我们动画运动框架的初稿。
框架升级---透明度兼容
但是针对透明度这个特殊的属性,所以我们说获取透明度通过opacity获取可以解决兼容性问题,但是设置透明度我们就需要对浏览器进行分类。
所以修改在给属性赋值去改变的时候,加以判断
if(k=="opacity") {
obj.style[k] = xinhaoliang[k];
obj.style.filter = "alpha(opacity="+xinhaoliang[k]*100+")";
} else {
obj.style[k] = xinhaoliang[k] + "px";
}
若属性是opacity,则给opacity和filter都赋值做到兼容。
框架升级---回调
假如我们想知道动画什么时候结束,那么需要传入一个回调函数,可以在动画结束时去回调。那么我们就需要在传参的时候多传入一个callback参数。
function animate(obj,endJson,time,callback) ,就想着这样。
count++;
if(count>=allcount) {
clearInterval(timer);
// 解锁
obj.isAnimated = false;
// 执行回调
callback.apply(obj);
}
我们可以在取消定时的时候去回调,当然回调的时候,我们可以回传参数。
apply call
我们先来看看外部调用的样式
animate(oDiv,{"width":400,"height":400,"opacity":1},1000,function() {
this.style.backgroundColor = "red";
animate(this,{"left":500},500,function() {
this.style.backgroundColor = "yellow";
animate(this,{"top":600},300,function() {
this.style.backgroundColor = "blue";
animate(this,{"left":40},500,function() {
})
})
})
});
上面有四个动画,每一个动画都是在上一个动画调用好之后,再去调用。
我们都知道,第一个参数是我们需要改变属性的对象,但是在回调的函数中我们是通过this的方式去传递,那么这个this指向的是谁?这在在后续js对象中会讲到,animate()=window.animate(),所以方法里面的this理应指向window,但是我们通过apply的方式给方法指向了一个this,所以此时的this是oDiv,
apply()
第一个参数表示指向的对象,第二个参数表示回传的参数,是一个数组。
call()
第一个参数表示指向的对象,第二个第三个...表示回传的参数。
<script type="text/javascript">
function sum(x,y,z) {
console.log(x+y+z);
console.log(this);
}
sum.call(oDiv[0],2,3,4);
sum.apply(oDiv[0],[5,6,7]);
</script>
框架升级---函数节流
试问一下,我们有一个需求通过点击事件去触发一个定时器,如果我们触发定时器的之前没有去清除定时器,那么定时器会叠加,要是定时器里有动画那么会越来越快。所以为了防止该情况,我们需要函数节流,也可以理解为锁。
所以我们可以改对象添加一个参数,来表示动画是否在进行,若在进行则去return。
在函数的最先面给函数添加参数obj.isAnimated = true;函数结束后obj.isAnimated = false;
完整代码
最后附上完整的代码
// 封装运动函数
function animate(obj,endJson,time,callback) {
if(obj.isAnimated){
return;
}
obj.isAnimated = true;
var start = {}; // 记住参与运动属性的初始值
// 循环得到最终状态json的属性,这些属性就是参与运动的属性
for(var k in endJson) {
start[k] = parseFloat(fetchComputedStyle(obj,k));
}
var stepJson = {}; // 记住运动属性的步长
var xinhaoliang = {};
for(var k in start) {
xinhaoliang[k] = start[k];
}
var interval = 50;
var allcount = time/interval;
var count = 0;
// 得到步长
for(var k in endJson) {
endJson[k] = parseFloat(endJson[k]);
stepJson[k] = (endJson[k] - start[k])/allcount;
}
// 运动
var timer = setInterval(function() {
for(var k in xinhaoliang) {
xinhaoliang[k] += stepJson[k];
if(k=="opacity") {
obj.style[k] = xinhaoliang[k];
obj.style.filter = "alpha(opacity="+xinhaoliang[k]*100+")";
} else {
obj.style[k] = xinhaoliang[k] + "px";
}
}
count++;
if(count>=allcount) {
clearInterval(timer);
// 解锁
obj.isAnimated = false;
// 执行回调
callback.apply(obj);
}
}, interval);
}
// 定义函数
function fetchComputedStyle(obj,property) {
// 用户输入的属性有两种情况 一种驼峰式一种是连字符写法
//高版本下 paddingLeft -------> padding-left
if(window.getComputedStyle) {
/*property = property.replace(/([A-Z])/g,function(match,$1) {
return "-"+$1.toLowerCase();
});*/
//console.log(property);
return getComputedStyle(obj)[property];
} else {
// padding-left------>paddingLeft
property = property.replace(/\-([a-z])/g,function(match,$1) {
return $1.toUpperCase();
});
return obj.currentStyle[property];
}
}
js的动画运动框架已讲完,接下来会来讲jquery,如有表达错的请谅解,并请提出指出,且修改错误,望能共同进步。