前面的运动,每次只能改一个值,你改div的width的时候,就不能改div的高度,改高度的时候就不能改宽度,如果我的运动想同时改宽度和高度,怎么实现?
在这里我们把属性和目标值用json实现。
在这个完美运动框架中,我们可以只让一个物体的一个属性运动,可以链式调用,也可以几个属性同时运动。能解决我们项目中遇到的大部分运动。

完美运动框架代码

function getStyle(obj,name){
  if(obj.currentStyle){
    return obj.currentStyle[name];
  }
  else{
    return getComputedStyle(obj,false)[name];
  }
}

function startMove(obj, json, fnEnd) {
  clearInterval(obj.timer);
  obj.timer = setInterval(function() {
    for(var attr in json){
      var cur=0;
      if(attr==="opacity"){
        cur=Math.round(parseFloat(getStyle(obj,attr))*100);//有可能会出现误差0.07*100
      }
      else{
        cur=parseInt(getStyle(obj,attr));
      }
      var speed = (json[attr] - cur) / 6;
      speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
      if (cur === json[attr]) {
        clearInterval(obj.timer);
        if(fnEnd)fnEnd();//运动结束后,如果fnEnd参数传递进去了就执行fnEnd函数
      } 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)
}

用完美运动框架做一个宽高同时运动的实例

<!DOCTYPE html>
<html>
  <head>
    <title>完美运动</title>
    <script src="move3.js"></script>
    <style>
      #div1{
        width: 100px;
        height: 100px;
        background: red;
        filter:alpha(opacity:30);
        opacity:0.3;
      }
    </style>
    <script>
      window.onload=function(){
        var oDiv=document.getElementById("div1");
        oDiv.onmouseover=function(){
          startMove(oDiv,{width:300,height:300,opacity:100});
        }
        oDiv.onmouseout=function(){
          startMove(oDiv,{width:100,height:100,opacity:30});
        }
      }
    </script>
  </head>
  <body>
    <div id="div1"></div>
  </body>
</html>

如果我们直接按照上面的方式,当我们运行下面代码的时候

startMove(oDiv,{width:101,height:300,opacity:100});

发现页面是有问题的,why?

if (cur === json[attr]) {
        clearInterval(obj.timer);
        if(fnEnd)fnEnd();//运动结束后,如果fnEnd参数传递进去了就执行fnEnd函数
      }

我们发现width先执行完成,当一个属性执行完成之后我们就关掉了定时器,所以没有达到我们预期的效果。我们看看怎么解决。
我们可以判断当所有值都达到目标点的时候在结束运动。

修改之后的运动框架如下

function getStyle(obj,name){
  if(obj.currentStyle){
    return obj.currentStyle[name];
  }
  else{
    return getComputedStyle(obj,false)[name];
  }
}

function startMove(obj, json, fnEnd) {
  clearInterval(obj.timer);
  obj.timer = setInterval(function() {
    var bStop=true;//假设:所有值都已经执行结束
    for(var attr in json){
      var cur=0;
      if(attr==="opacity"){
        cur=Math.round(parseFloat(getStyle(obj,attr))*100);//有可能会出现误差0.07*100
      }
      else{
        cur=parseInt(getStyle(obj,attr));
      }
      var speed = (json[attr] - cur) / 6;
      speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
      if(cur!=json[attr]){//假设有没到目的地的值我们设置为false
        bStop=false;
      }
      if(attr==="opacity"){
        obj.style.filter="alpha(opacity:"+cur+speed+")";
        obj.style.opacity=(cur+speed)/100;
      }else{
        obj.style[attr]=cur+speed+"px";
      }
    }
    if (bStop) {//如果bStop为true代表值都到目的地,这时候我们才关定时器
      clearInterval(obj.timer);
      if(fnEnd)fnEnd();//运动结束后,如果fnEnd参数传递进去了就执行fnEnd函数
    }
  }, 30)
}

测试例子如下

<!DOCTYPE html>
<html>
  <head>
    <title>完美运动</title>
    <script src="move4.js"></script>
    <style>
      #div1{
        width: 100px;
        height: 100px;
        background: red;
        filter:alpha(opacity:30);
        opacity:0.3;
      }
    </style>
    <script>
      window.onload=function(){
        var oDiv=document.getElementById("div1");
        oDiv.onmouseover=function(){
          startMove(oDiv,{width:101,height:300,opacity:100});
        }
        oDiv.onmouseout=function(){
          startMove(oDiv,{width:100,height:100,opacity:30});
        }
      }
    </script>
  </head>
  <body>
    <div id="div1"></div>
  </body>
</html>

到目前为止,我们可以在任何地方用我们的运动框架做运动效果。

运动框架演变过程

图片描述

运动实现留言板的例子

<!DOCTYPE html>
<html>
  <head>
    <title>完美运动</title>
    <script src="move4.js"></script>
    <style>
      *{
        margin: 0;
        padding: 0;
      }
      #ul1{
        width: 400px;
        height: 400px;
        border: 1px solid #000;
        margin: 10px auto;
        overflow: hidden;
      }

      #ul1 li{
        border-bottom: 1px dashed #999;
        padding: 4px;
        list-style: none;
        overflow: hidden;
        filter:alpha(opacity:0);
        opacity:0;
      }
    </style>
    <script>
      window.onload=function(){
        var oBtn=document.getElementById("btn1");
        var oTxt=document.getElementById("txt1");
        var oUl=document.getElementById("ul1");
        oBtn.onclick=function(){
          var oLi=document.createElement("li");
          oLi.innerHTML=oTxt.value;
          oTxt.value="";
          if(oUl.children.length>0){
            oUl.insertBefore(oLi,oUl.children[0]);
          }else{
            oUl.appendChild(oLi);
          }
          // 运动,高度展开
          var iHeight=oLi.offsetHeight;
          oLi.style.height=0;
          startMove(oLi,{height:iHeight},function(){
            startMove(oLi,{opacity:100});
          });

        }
      }
    </script>
  </head>
  <body>
    <textarea id="txt1" rows="4" cols="40"></textarea>
    <input id="btn1" type="button" value="发布" />
    <ul id="ul1">
      
    </ul>
  </body>
</html>

666888
334 声望10 粉丝

知其然且知其所以然。