javascript 匀速动画封装
匀速: 顾名思义就是速度保持不变的运动。假如从A地去B地距离是1000m,那么如果按照100m/min的速度运动,那么就需要10分钟。假如从A地出发的时刻开始计时,那么5分钟之后应该运动到500m的位置。如果从500m的位置开始出发那么5分钟之后应该到达1000m的位置。如果从200m处出发那么5分钟之后就该到达700m的位置。从而得到一个计算当前位置的运算公式:
当前的位置 = 花费的时间 / 规定的时间 * 改变的距离 + 起点位置
//@param t 已经花费的时间
//@param b 开始的起点位置
//@param c 改变的距离 = 终点 - 起点
//@param d 规定完成运动的时间
function linear(t,b,c,d){
reutrn t/d*c + b;
}
那么开始规定动画函数需要的参数:
1 运动的元素
2 运动的终点 => 起点获取元素当时已经生效的样式即可
3 运动的时间间隔
4 运动结束之后要执行的函数(回调函数)
// @param ele 运动元素
// @param target 终点
// @param duration 规定时间内完成运动
// @callback 运动结束后执行的函数 => 动画结束之后还要做什么
function (ele,target,duration,callback){
var linearEffect = function (t,b,c,d){ //匀速计算公式返回值是应该运动到的位置
return t/d*c + b;
}
//开始准备运动需要的t,b,c,d
var time = 0; //刚开始花费的时间为0 => 公式中的t
var begin = {}; //开始的位置可以根据target来获取,如果target运动的终点只是在width和opacity运动,那么我们只需要操作这两个维度即可,所以获取当前的开始时刻的样式就根据target来获取
var change = {};
var interval = 10; //定时器的时间间隔
for(var key in target){ //遍历target
begin[key] =
utils.getCss(ele,key); // utils.getCss是用来获取样式的方法,在使用之前需要先引入utils工具包,其他文章有介绍这个方法
change[key] =
target[key] - begin[key]; //改变的距离是终点-起点
}
ele.timer && window.clearInterval(ele.timer); //只要运动的元素有自定义属性保存着定时器那么在下一次执行的时候一定要把上一次的定时器清掉,无论是否已经到达终点
// js中的动画是用定时器不断驱动的,当时间间隔足够小就形成了视觉动画
ele.timer = window.setInterval(function (){
time += interval; // 每次执行定时器花费的时间都会累加根据匀速公式从而引发位置变化
if(time >= duration){ //当花费时间超过规定时间就是到达终点
window.clearInterval(ele.timer); // 到达终点清空定时器
utils.css(ele,target); // 主动设置终点值
if(typeof callback == 'function'){ //到达终点之后如果想继续执行其他操作比如修改元素的其他样式或者内容等那么就需要回调函数。这个函数就会在运动到达终点之后执行,运动过程中不执行
callback.call(ele); //把回调函数中的this修改成运动的那个元素
}
return;
}
for(var key in change){
if(change[key]){ //在当前这个维度上有值的变化才去运动
var val = linearEffect(time,begin[key],change[key],duration);
utils.setCss(ele,key,val);
}
}
},interval);
}
js中的动画都是使用定时器来不断驱动需要动画的属性的值不断变化,从而在视觉上造成连续的动画效果。定时器的时间间隔一般不宜过大。一般设置在10左右。不同浏览器识别定时器都有最小时间间隔。chrome大约7ms ,IE大约12ms