JavaScript 完美运动框架原理与实现解析
本文深入解析 JavaScript 完美运动框架,解决传统框架无法同时处理多个属性运动的局限。通过引入 JSON 对象传递目标值,利用布尔标志位 bStop 判断所有动画是否结束,实现多物体、多属性的同步平滑运动,并支持回调函数处理后续逻辑。
完美运动框架概述与局限
从名称即可看出,该框架旨在实现网络上常见的各类视觉效果。然而,早期的运动框架存在明显局限,主要体现为无法同时驱动多个属性值进行运动。
针对这一痛点,我们需要回顾并分析原有的运动框架结构。
原有框架代码分析
function getStyle(obj, name) {
if (obj.currentStyle) {
return obj.currentStyle[name];
} else {
return getComputedStyle(obj, null)[name];
}
}
function startMove(obj, attr, iTarget) {
clearInterval(obj.time);
obj.time = setInterval(function() {
var cur = 0;
if (attr == 'opacity') {
cur = Math.round(parseFloat(getStyle(obj, attr)) * 100);
} else {
cur = parseInt(getStyle(obj, attr));
}
var speed = (iTarget - cur) / 6;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if (cur == iTarget) {
clearInterval(obj.time);
} else {
if (attr == 'opacity') {
obj.style.filter = 'alpha(opacity=' + cur + speed + ')';
obj.style.opacity = (cur + speed) / 100;
} else {
obj.style[attr] = cur + speed + 'px';
}
}
}, 30);
}
修改方案十分直观:在旧版框架中,每次调用仅能接收单个样式属性及其对应数值;新版框架将其重构为接收一个 JSON 对象,从而允许同时指定多个样式属性及其目标值。
调用方式示例为 startMove(oDiv,{width:200,height:200});,若需执行动画结束后的操作,可额外传入回调函数。接下来详细解析代码的具体修改逻辑。
完美框架实现原理
function startMove(obj, json, fnEnd)
{
var MAX=18;
//每次调用就只有一个定时器在工作(开始运动时关闭已有定时器)
//并且关闭或者开启都是当前物体的定时器,已防止与页面上其他定时器的冲突,使每个定时器都互不干扰
clearInterval(obj.timer);
obj.timer=setInterval(function (){
var bStop=true; // 假设:所有的值都已经到了
for(var name in json)
{
var iTarget=json[name]; // 目标点
//处理透明度,不能使用parseInt否则就为0了
if(name=='opacity')
{
// *100 会有误差 0000007 之类的 所以要用 Math.round() 会四舍五入
var cur=Math.round(parseFloat(getStyle(obj, name))*100);
}
else
{
var cur=parseInt(getStyle(obj, name)); // cur 当前移动的数值
}
var speed=(iTarget-cur)/5; // 物体运动的速度 数字越小动的越慢 /5 : 自定义的数字
speed=speed>0?Math.ceil(speed):Math.floor(speed);
if(Math.abs(speed)>MAX)speed=speed>0?MAX:-MAX;
if(name=='opacity')
{
obj.style.filter='alpha(opacity:'+(cur+speed)+')'; //IE
obj.style.opacity=(cur+speed)/100; //ff chrome
}
else
{
obj.style[name]=cur+speed+'px';
}
// 某个值不等于目标点
if(cur!=iTarget)
{
bStop=false;
}
}
// 都达到了目标点
if(bStop)
{
clearInterval(obj.timer);
if(fnEnd) //只有传了这个函数才去调用
{
fnEnd();
}
}
}, 20);
}
为何需要引入 bStop 这一假设变量?
考虑一种边界情况:若调用 startMove(oDiv,{width:101,height:200});,其中宽度属性已到达目标值 101,但高度尚未到达 200。若此时直接关闭定时器,会导致高度运动中断,从而产生特定的逻辑 Bug。
正确的逻辑应当是:仅当所有指定的运动属性均到达目标值时,才关闭定时器;反之,只要有一个属性未到达,定时器就应继续运行。在代码实现上,这通过定义一个初始值为 true 的布尔变量 bStop 来模拟判断。
具体逻辑为:假设所有值均已到达(bStop=true),若遍历中发现任一属性值不等于目标点,则将 bStop 设为 false。当整个运动循环结束后,若 bStop 仍为 true,则表明所有运动属性均已到位,此时方可安全关闭定时器。
至此,该运动框架的核心功能已基本完善,需注意其适用范围为 CSS2 属性,暂不支持 CSS3 新特性。
核心要点总结。
运动框架演进历程
运动框架的迭代演进路径如下:
startMove(iTarget) 基础运动框架 startMove(obj,iTarget) 支持多物体 startMove(obj,attr,iTarget) 支持任意单一值 startMove(obj,attr,iTarget,fn) 支持链式运动 startMove(obj,json,fn) 完美运动框架
感谢阅读。
JS监听滚动事件:回到顶部按钮的显示与隐藏逻辑
2026-11-05 16:19:37
JavaScript怎么读写LocalStorage与SessionStorage
2026-11-05 15:40:11
anime.js 与 GSAP 对比:轻量级项目该怎么选择动画库
2026-11-05 11:24:55
flv.js 与 hls.js 在直播场景下的选型对比
2026-11-05 08:18:52
JavaScript能做什么?前端开发中的作用与应用场景解析
2026-11-04 23:17:54
