本文介绍如何使用原生JavaScript实现类似jQuery的animate()动画函数。详细解析obj、json、interval、sp及回调函数fn等参数含义,重点阐述定时器隔离、多属性同步判断及数值取整等关键实现细节,并提供完整代码示例供参考。
背景与动机
经过一个月的实习,我对CSS和HTML的使用已较为熟练,近期开始深入JavaScript开发。今日尝试用原生JS编写了一个模拟jQuery animate()函数的动画模块,经测试性能表现良好。个人认为jQuery作为框架并非万能,其内部实现往往较为固化,例如animate()函数可选参数有限,有时难以满足特定的复杂动画需求。
代码中注释部分主要用于测试验证。编写过程并非一帆风顺,由于平时对JS底层细节关注较少,仅停留在宏观理解层面,但在实际实现动画逻辑时,细微的代码错误往往会导致调试困难。
函数参数详解
以下对该函数涉及的关键参数进行逐一解释:
• obj:目标操作对象。
• json:包含目标属性值的键值对对象,格式为{attr: 'value', attr: 'value'},指定需要执行动画的元素属性。
• interval:每次状态更新的间隔时间,即控制属性值变化的频率。
• sp:变化速率系数,用于实现缓冲效果,避免动画仅以匀速(sp为1时)进行,使运动更自然。
• fn:回调函数,动画执行完毕后触发的行为逻辑。
核心实现细节
代码逻辑相对简单,但有几个关键细节需要特别注意:
• 目标对象的属性无需预先声明,因此函数首行的clearInterval(obj.timer);不会引发错误,即使timer未定义也会安全执行。
• 必须为每个操作对象分配独立的定时器实例。若多个对象共用一个定时器,会导致运动状态相互干扰,出现明显的卡顿现象。
• 需关注json数据格式的处理。在遍历对象的动画属性时,通过判断icur != json[arr]来确认每个属性是否已到达目标值。flag变量用于防止因部分属性提前达到目标而误清定时器。每次遍历前将flag初始化为true,若发现任一属性未达标,则将flag置为false。只有当所有属性均达到目标值时,才清除定时器。
• speed = speed > 0 ? Math.ceil(speed): Math.floor(speed);
该语句的作用是对属性变化值进行取整处理,因为除opacity外的CSS属性值通常不支持小数。
• 调用时需特别注意动画对象的作用域。在使用for循环时,应避免随意使用arr[i]形式,特别是在嵌套循环中,变量i的值可能已变为最大值,导致引用错误。
代码实现与调用
js
function animate(obj, json, interval, sp, fn) {
clearInterval(obj.timer);
//var k = 0;
//var j = 0;
function getStyle(obj, arr) {
if(obj.currentStyle){
return obj.currentStyle[arr]; //针对ie
} else {
return document.defaultView.getComputedStyle(obj, null)[arr];
}
}
obj.timer = setInterval(function(){
//j ++;
var flag = true;
for(var arr in json) {
var icur = 0;
//k++;
if(arr == "opacity") {
icur = Math.round(parseFloat(getStyle(obj, arr))*100);
} else {
icur = parseInt(getStyle(obj, arr));
}
var speed = (json[arr] - icur) * sp;
speed = speed > 0 ? Math.ceil(speed): Math.floor(speed);
if(icur != json[arr]){
flag = false;
}
if(arr == "opacity"){
obj.style.filter = "alpha(opacity : '+(icur + speed)+' )";
obj.style.opacity = (icur + speed)/100;
}else {
obj.style[arr] = icur + speed + "px";
}
//console.log(j + "," + arr +":"+ flag);
}
if(flag){
clearInterval(obj.timer);
//console.log(j + ":" + flag);
//console.log("k = " + k);
//console.log("j = " + j);
//console.log("DONE");
if(fn){
fn();
}
}
},interval);
}
调用方式示例如下:
<script>
var move = document.getElementById("move").getElementsByTagName("li");
for(var i = 0; i < move.length; i ++){
move[i].onmouseover = function(){
var _this = this;
animate(_this, {width: 500, height: 200},10, 0.01, function(){
animate(_this, {width: 300, height: 200},10, 0.01);
});
}
}
</script>
以上关于原生JS实现jQuery animate()动画效果的实例分享完毕,希望能为读者提供有价值的参考,欢迎支持本站更多内容。