js运动

      • 匀速运动
      • 小练习;页面滑出插件
      • getStyle函数应用
      • 改变多个对象宽度
      • 通过startMove让元素的多个属性同时发生变化
      • 重点:多物体、多值、链式调用框架

运动的本质——>物体的状态发生连续性的变化

匀速运动

js运动_第1张图片

<divstyle="height:100px; width:100px; background: orange; position:absolute; left:0px; top: 0px;">div>
<button style="position: absolute; left:0px; top:150px;">runbutton>
<span style="width:1px; height:100px; background:black; position:absolute; left:300px; top:0px;"> span>


<script>
  var oDiv = document.getElementsByTagName('div')[0],
      oBtn = document.getElementsByTagName('button')[0],
      iSpeed = 10,  //控制速度
      timer;

  oBtn.onclick = function () {
      startMove(oDiv);
  }

  function startMove (obj) {
      clearInterval(timer); //开启定时器之前,先把上一个定时器清除
      timer = setInterval(function () {
         obj.style.left = obj.offsetLeft + iSpeed + 'px';
      },30)
  }




script>

添加条件;到达300位置停止
js运动_第2张图片

function startMove (obj) {
    clearInterval(timer);
    timer = setInterval(function () {
        if(obj.offsetLeft === 300) {  //判断如果到达300的位置,就停止运动
            clearInterval(timer);
        }else{
            obj.style.left = obj.offsetLeft + iSpeed + 'px';
        }
    },30)
}

当iSpeed不被300整除时,让方块停到300

function startMove (obj) {
  clearInterval(timer);
  timer = setInterval(function () {
      if(obj.offsetLeft >= 300) {  //判断如果到达300的位置,就停止运动
          clearInterval(timer);
          obj.style.left = '300px'; //超过后,让方块回来一点点,正好停在300位置
      }else{
          obj.style.left = obj.offsetLeft + iSpeed + 'px';
      }
  },30)
}

或者

function startMove (obj) {
  clearInterval(timer);
  timer = setInterval(function () {
      if(300 - obj.offsetLeft < iSpeed) {  //判断如果终点和方块位置的差小于步长,就停止定时器;
          clearInterval(timer);
          obj.style.left = '300px'; 
      }else{
          obj.style.left = obj.offsetLeft + iSpeed + 'px';
      }
  },30)
}

如果方块在300的右侧
js运动_第3张图片

function startMove (obj) {
   clearInterval(timer);
   if(obj.offsetLeft > 300) {
       iSpeed = -8; //如果方块在终点右侧,则速度为负
   }else{
       iSpeed = 8;  //如果方块在终点左侧,则速度为正
   }
   timer = setInterval(function () {
       if(Math.abs(300 - obj.offsetLeft) < Math.abs(iSpeed)) {  //判断方块与终点的差,是否小于步长
           clearInterval(timer);
           obj.style.left = '300px';
       }else{
           obj.style.left = obj.offsetLeft + iSpeed + 'px';
       }
   },30)
}

缓冲运动

function startMove (obj) {
    clearInterval(timer);
    timer = setInterval(function () {
        iSpeed = (300 - obj.offsetLeft) / 7; 
        console.log(iSpeed); //最后会在0.14左右无限循环
        obj.style.left = obj.offsetLeft + iSpeed + 'px';
    },30)
}

js运动_第4张图片

offsetLeft是向下取整的,所以加上的iSpeed如果小于1;那么就永远无法到达300位置,永远停留在299的位置上;
所以需要给iSpeed判断;

function startMove (obj) {
    clearInterval(timer);
    timer = setInterval(function () {
        iSpeed = (300 - obj.offsetLeft) / 7;
        iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
        //如果方块在左侧;则iSpeed大于0,向上取整。
        //如果方块在右侧;则iSpeed小于0,向下取整。
        if(obj.offsetLeft === 300) {
            clearInterval(timer)
        }else {
            obj.style.left = obj.offsetLeft + iSpeed + 'px';
        }
    },30)
}

小练习;页面滑出插件

js运动_第5张图片
js运动_第6张图片

var oDivWrapper = document.getElementsByTagName('div')[0],
    timer = null;

oDivWrapper.onmouseenter = function () {
    startMove(this, 0); //鼠标移入弹出
}

oDivWrapper.onmouseleave = function () {
    startMove(this, -400); //鼠标移出弹回
}

function startMove (obj,target) { //target为目标点
    clearInterval(timer);
    var iSpeed;
    timer = setInterval(function () {
        iSpeed = (target - obj.offsetLeft) / 7;
        iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
        if(obj.offsetLeft === target) {
            clearInterval(timer);
        }else {
            obj.style.left = obj.offsetLeft + iSpeed + 'px';
        }
    },30)
}

getStyle函数应用

function getStyle(obj, attr) {
   if(obj.currentStyle) {
       return obj.currentStyle[attr];
   }else{
       return window.getComputedStyle(obj, false)[attr];
   }
}
 <div style="width:100px;height:100px;background:red;opacity:0.9">div>

<script>
    console.log(getStyle(oDiv, 'width'), typeof(getStyle(oDiv, 'width')));
    //  100px string

    console.log(getStyle(oDiv, 'opacity'), typeof(getStyle(oDiv, 'opacity')));
    // 0.9 string

    console.log(parseInt(getStyle(oDiv, 'width')), typeof(getStyle(oDiv, 'width')));
    // 100 "string"

    console.log(parseFloat(getStyle(oDiv, 'opacity')), typeof(getStyle(oDiv, 'opacity')));
    // 0.9 "string"
script>

js运动_第7张图片

<div style="width:100px;height:100px;background:red;opacity:0.9">div>
<script>
    var oDiv = document.getElementsByTagName('div')[0];
    var timer = null;

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

    function startMove(obj, target) {
        clearInterval(timer);
        var iSpeed;
        timer = setInterval(function () {
            iSpeed = (target - getStyle(obj, 'opacity')); 
            //target<= 1; opacite <= 1;
            //所以,iSpeed取整之后,不是 +1 就是 0 或者 -1;
            iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); 
            obj.style.opacity = parseFloat(getStyle(obj, 'opacity')) + iSpeed;
            //opacity加上 -1 再向下取整是 -1;而opacity的最小值是0,这时target - opacity的值为正,iSpeed的值就为1,所以,对象的透明度在0与1之间来回变化
        }, 30)
    }

    startMove(oDiv, 0.5)

script>

opacity加上 -1 再向下取整是 -1;而opacity的最小值是0,这时target - opacity的值为正,iSpeed的值就为1,所以,对象的透明度在0与1之间来回变化;

解决方法,把数据扩大100倍,最后再/100;

function startMove(obj, target) {
    clearInterval(timer);
    var iSpeed,
        iCur; //当前值
    timer = setInterval(function () {
        iCur = getStyle(obj, 'opacity') * 100;
        iSpeed = (target - iCur) / 7;   
        //当前值扩大了100倍,这里的target(目标值)也要扩大100倍
        iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
        if(iCur == target) {
            clearInterval(timer);
        }else{
            obj.style.opacity = (iCur + iSpeed) / 100;
        }
    }, 30)
}

oDiv.onclick = function () {
    startMove(oDiv, 50);
}

改变多个对象宽度

js运动_第8张图片

var oDivArray = document.getElementsByTagName('div');
var timer = null;

for(var i = 0; i < oDivArray.length; i++) {
    oDivArray[i].onmouseenter = function () {
        startMove(this, 400); //鼠标移入改变当前对象宽度
    }
    oDivArray[i].onmouseleave = function () {
        startMove(this, 100);  //鼠标移出,把当前的宽度变回100
    }
}


function startMove (obj,target) {
    clearInterval(timer);
    var iSpeed;
    timer = setInterval(function () {
        iSpeed = (target - obj.offsetWidth) / 7;
        iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
        if(obj.offsetWidth === target) {
            clearInterval(timer);
        }else {
            obj.style.width = obj.offsetWidth + iSpeed + 'px';
        }
    },30)
}

因为都在一个定时器里面,所以,鼠标快速移动时,上一个定时器还没有执行完,下一个定时器就开启了;在开启下一个定时器时,又把上一个定时器删除了,所以上一个对象就不能恢复到100了

解决方法

把定时器变成每一个对象的自身属性;清理时也清除自身的这个属性

function startMove (obj,target) {
   clearInterval(obj.timer);
   var iSpeed;
   obj.timer = setInterval(function () {
       iSpeed = (target - obj.offsetWidth) / 7;
       iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
       if(obj.offsetWidth === target) {
           clearInterval(obj.timer);
       }else {
           obj.style.width = obj.offsetWidth + iSpeed + 'px';
       }
   },30)
}

通过startMove让元素的多个属性同时发生变化

js运动_第9张图片

oDivArray[0].onclick = function () {
   startMove(this, 400, 'width');
}
oDivArray[1].onclick = function () {
   startMove(this, 400, 'height');
}
oDivArray[2].onclick = function () {
   startMove(this, 50, 'opacity');
}
oDivArray[3].onclick = function () {
   startMove(this, 10, 'borderWidth');
}

function startMove (obj, target, attr) {
    clearInterval(obj.timer);
    var iSpeed;
    obj.timer = setInterval(function () {
        if(attr == 'opacity') {
            iCur = parseFloat(getStyle(obj, attr)) * 100;
        }else {
            iCur = parseInt(getStyle(obj, attr));
        }
        iSpeed = (target - iCur) / 7;
        iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);

        if(iCur === target) {
            clearInterval(obj.timer); 
        }else {
            if(attr == 'opacity') {
                obj.style.opacity = (iCur + iSpeed) / 100;
            }else {
                obj.style[attr] = iCur + iSpeed + 'px';
            }
        }
    },30)
}

重点:多物体、多值、链式调用框架

js运动_第10张图片

js运动_第11张图片

var oDivArray = document.getElementsByTagName('div');
var timer = null;

var targetObj = {
    width: 400,
    height: 400,
    opacity: 50,
    left: 300,
    top: 200
}


oDivArray[0].onclick = function () {
   startMove(this, targetObj, function () {
       startMove(oDivArray[1], targetObj);
   });
}

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

function startMove(obj, json, callback) {
  clearInterval(obj.timer);
  var iSpeed,
      iCur;
  obj.timer = setInterval(function () {
      var bStop = true;
      for(var attr in json) {
          if(attr == 'opacity') {
              iCur = parseFloat(getStyle(obj, attr)) * 100;
          }else {
              iCur = parseFloat(getStyle(obj, attr));
          }
          iSpeed = (json[attr] - iCur) / 7;
          iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
          if(attr == 'opacity') {
              obj.style.opacity = (iCur + iSpeed) / 100;
          }else {
              obj.style[attr] = iCur + iSpeed + 'px';
          }
          if(iCur != json[attr]) {
              bStop = false;
          }
          if(bStop) {
              clearInterval(obj.timer);
              typeof callback == 'function' ? callback() : ''; //判断参数是否是函数,是就执行(链式调用);
          }
      }
  }, 30)
}

你可能感兴趣的:(javascript,js运动)