单方向指定时间内的匀速运动

 回忆匀速运动:
 y = kx + b;
这里的各参数表示的含义:
k:其实是速度,总路程/总时间
x:表示经过的时间
b:表示一开始所在的位置
y:表示当经过的时间是x的时候,走过的路程

用函数表示

  /**
   * @param    {[type]}   start   [开始位置]
   * @param    {[type]}   alter   [改变的距离]
   * @param    {[type]}   curTime [已运行的时间]
   * @param    {[type]}   dur     [总时间]
   * @return   {[type]}           [返回当前时间的所在位置]
   */
  function linear(start, alter, curTime, dur) {
    return start + alter / dur * curTime;
  }

现在想让一个盒子用500ms从left=10匀速运动到20.
这里有一个问题,就是如果500ms的时候,对应的距离大于20,那么则调整为等于20

先把准备工作做好

  var start = 10,
    target = 20,
    dur = 500;
  var alter = target - start,
    curTime = 0;
  var y = 0;
  // interval  影响curTime值
  var interval = 11;

然后用两种定时方式实现

setInterval:

  var timer = window.setInterval(animate, interval);
  function animate () {
      curTime += interval;
      y = linear(start, alter, curTime, dur);
      console.log(y);
      if (y >= target) {
          y = target;
          box.style.left = y + "px";
          window.clearInterval(timer);
          timer = null;
          return;
      }
      box.style.left = y + "px";
  }

 

setTimeout:

  var timer = window.setTimeout(animate, interval);
  function animate () {
      window.clearTimeout(timer);
      curTime += interval;
      y = linear(start, alter, curTime, dur);
      console.log(y);
      if (y >= target) {
          y = target;
          box.style.left = y + "px";
          timer = null;
          return;
      }
      box.style.left = y + "px";
      timer = window.setTimeout(animate, interval);
  }

但是因为setInterval有累积效应,所以为了更好的效果,一般用setTimeout ,如上述代码看到的,学会将setInterval转化为setTimeout

(回调函数第一行加清除,最后一行加启动)

以下只写setTimeout

html结构 和 css样式

 <style>
  #box {
    width: 100px;
    height: 100px;
    background-color: #f79;
    position: absolute;
    left: 10px;
  }
  </style>


<div id="box"></div>

 

 

贴下全部代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
  #box {
    width: 100px;
    height: 100px;
    background-color: #f79;
    position: absolute;
    left: 10px;
  }
  </style>
</head>

<body>
  <div id="box"></div>
  <script>
  /*
   *  匀速运动:
   *  y = kx + b;
   *
   * 想想 这里的各参数表示的含义:
   * k:其实是速度,总路程/总时间
   * x:表示经过的时间
   * b:表示一开始所在的位置
   * y:表示当经过的时间是x的时候,走过的路程
   */
  /**
   * [linear description]
   * @Author   zhm
   * @DateTime 2017-02-21
   * @param    {[type]}   start   [开始位置]
   * @param    {[type]}   alter   [改变的距离]
   * @param    {[type]}   curTime [已运行的时间]
   * @param    {[type]}   dur     [总时间]
   * @return   {[type]}           [返回当前时间的所在位置]
   */
  function linear(start, alter, curTime, dur) {
    return start + alter / dur * curTime;
  }

  /*
   * 现在想让盒子用500ms从left=10匀速运动到20.
   * 这里有一个问题,就是如果500ms的时候,对应的距离大于20,那么则调整为等于20
   */
  var start = 10,
    target = 20,
    dur = 500;
  var alter = target - start,
    curTime = 0;
  var y = 0;
  // interval  影响curTime值
  var interval = 11;
 
 /* 
 var timer = window.setInterval(animate, interval);
  function animate () {
      curTime += interval;
      y = linear(start, alter, curTime, dur);
      console.log(y);
      if (y >= target) {
          y = target;
          box.style.left = y + "px";
          window.clearInterval(timer);
          timer = null;
          return;
      }
      box.style.left = y + "px";
  }

*/
  
  var timer = window.setTimeout(animate, interval);
  function animate () {
      window.clearTimeout(timer);
      curTime += interval;
      y = linear(start, alter, curTime, dur);
      console.log(y);
      if (y >= target) {
          y = target;
          box.style.left = y + "px";
          timer = null;
          return;
      }
      box.style.left = y + "px";
      timer = window.setTimeout(animate, interval);
  }
  </script>
</body>

</html>

 索性将这一套变成定义成方法,这样单方向的匀速运动基本都能用了

 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
  #box {
    width: 100px;
    height: 100px;
    background-color: #f79;
    position: absolute;
    left: 10px;
  }
  </style>
</head>

<body>
  <div id="box"></div>
  <script>
  styleAnimate(box, "left", 100, 300, 10, linear);

  function linear(start, alter, curTime, dur) {
    return start + alter / dur * curTime;
  }

  function styleAnimate(ele, attr, target, dur, interval, way) {
    var start = rmPx(window.getComputedStyle(ele, null)[attr]) - 0, // 不要单位,且变成数字类型
      alter = target - start,
      curTime = 0;
    var y = 0;
    var timer = window.setTimeout(animate, interval);

    function animate() {
      window.clearTimeout(timer);
      curTime += interval;
      way = way || linear;
      y = way(start, alter, curTime, dur);
      console.log(y);
      if (y >= target) {
        y = target;
        // 加单位,这里默认加px,如果是别的,加第二个参数即可
        ele.style[attr] = addPx(y);
        timer = null;
        return;
      }
      ele.style[attr] = addPx(y);
      timer = window.setTimeout(animate, interval);
    }

    // 检测字符串有没有px之类的单位
    function hasPx(str) {
      return /^(\d+)(px|em|rem)$/.test(str);
    }
    // 字符串有单位的话去掉
    function rmPx(str) {
      if (hasPx(str)) {
        return /^(\d+)(px|em|rem)$/.exec(str)[1];
      }
      return str;
    }
    // 给纯数字的且没单位的字符串加单位
    function addPx(str, unit) {
      if (hasPx(str) || (str + "") === "0") {
        return str;
      }
      if (/^\d+$/.test(str)) {
        unit = unit || "px";
        return str + unit;
      }
    }
  }
  </script>
</body>

</html>

 以上情况只是 target>start,那么包含小于和等于的情况,对于最终的animate

  function animate() {
    window.clearTimeout(timer);
    way = way || linear;
    y = way(start, alter, curTime, dur);
    // 这里开始判断target和start的大小
    if (target = start) {
      return;
    }
    if (target > start) {
      curTime += interval;
      y >= target && afterTarget();
    } else if (target > start) {
      curTime -= interval;
      y <= target && afterTarget();
    } else {
      return;
    }

    console.log(y);
    // 超出范围之后,清除定时器,重置属性
    function afterTarget() {
      y = target;
      // 加单位,这里默认加px,如果是别的,加第二个参数即可
      ele.style[attr] = addPx(y);
      timer = null;
      return;
    }

    ele.style[attr] = addPx(y);
    timer = window.setTimeout(animate, interval);
  }

 

posted @ 2017-02-21 17:53  花.花  阅读(260)  评论(0编辑  收藏  举报