JavaScript 完美运动框架原理与实现解析

作者:页面旅途时间:2026-10-28 20:40:20浏览:184

本文深入解析 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) 完美运动框架

感谢阅读。

作者最新文章