完成多个setInterval函数时执行代码

时间:2014-12-20 23:57:10

标签: javascript html5 multithreading css3 css-animations

大家好,并提前感谢您的时间!

我正在开发一个涉及CSS3动画同步的网站。我正在使用setInterval()调用来运行动画。我正在寻找在动画完成后调用函数的最佳方法。

下面的代码只是解释我的问题的一般样本。按下开始按钮时,将调用三个setInterval()函数。一个动画转换,一个动画缩放,最后一个动画旋转。我的问题的实质是,如何运行一些代码 - 为了论证,让我们说console.log("我们做了IT!"); - 调用最后一个clearInterval()时。

我可以想象一个布尔网络跟踪动画已经完成并在抛出所有标志时调用代码,但我希望有一个更优雅的解决方案可以在这里找到。

再次感谢!



//Global Variable Declarations
var adc = adc || {};
adc.tWrap = document.createElement('div');
adc.sWrap = document.createElement('div');
adc.rWrap = document.createElement('div');
adc.btn = document.createElement('button');

//Style Objects, Append to Body, Apply Listeners
adc.init = function() {
  adc.setDiv(adc.tWrap, "transform wrap", 22, 22, 200, 200, 1, "");
  adc.setDiv(adc.sWrap, "scale wrap", 22, 22, 150, 150, 2, "", "");
  adc.setDiv(adc.rWrap, "rotate wrap", 22, 22, 100, 100, 3, "yellow");

  adc.setBtn(adc.btn, "start btn", 25, 25, 50, 50, "Start");
  var body = document.getElementsByTagName('body');
  body[0].appendChild(adc.tWrap);
  adc.tWrap.appendChild(adc.sWrap);
  adc.sWrap.appendChild(adc.rWrap);
  adc.rWrap.appendChild(adc.btn);

  adc.btn.addEventListener('click', adc.click, true);
}
adc.setDiv = function(a, id, T, L, H, W, z, bg) {
  a.id = id;
  a.style.position = 'absolute';
  a.style.top = T + "px";
  a.style.left = L + "px";
  a.style.height = H + "px";
  a.style.width = W + "px";
  a.style.zIndex = z;
  a.style.borderWidth = "3px";
  a.style.borderStyle = "solid";
  a.style.backgroundColor = bg;
}
adc.setBtn = function(a, id, T, L, H, W, txt) {
  a.id = id;
  a.type = "button";
  a.textContent = txt;
  a.style.position = 'absolute';
  a.style.top = T + "px";
  a.style.left = L + "px";
  a.style.height = H + "px";
  a.style.width = W + "px";
}

//Event Listener
adc.click = function() {
  if (!adc.animate.runLock()) {
    adc.animate.trans.start();
    adc.animate.scale.start();
    adc.animate.rotate.start();
  }
}

//Animation Routines (setInterval calls)
adc.animate = {
  runLock: function() {
    if (adc.animate.trans.run == 0 && adc.animate.scale.run == 0 && adc.animate.rotate.run == 0) {
      return false;
    } else {
      return true;
    }
  },
  trans: {
    run: 0,
    count: 0,
    flag: false,
    start: function() {
      this.run = setInterval(function() {
        adc.animate.trans.EXE()
      }, 10);
    },
    stop: function() {
      clearInterval(this.run);
      this.run = this.count = 0;
      this.flag = false;
    },
    EXE: function() {
      if (!this.flag) {
        this.count += 0.5;
      } else {
        this.count -= 0.5;
      }
      if (this.count >= 45) {
        this.flag = true;
      }
      adc.tWrap.style.transform = "translateX(" + this.count + "px)";
      if (this.count <= 0) {
        this.stop();
      }
    }
  },
  scale: {
    run: 0,
    count: 1,
    flag: false,
    start: function() {
      this.run = setInterval(function() {
        adc.animate.scale.EXE()
      }, 10);
    },
    stop: function() {
      clearInterval(this.run);
      this.run = 0;
      this.count = 1;
      this.flag = false;
    },
    EXE: function() {
      if (!this.flag) {
        this.count += 0.01;
      } else {
        this.count -= 0.01;
      }
      if (this.count >= 1.9) {
        this.flag = true;
      }
      adc.sWrap.style.transform = "scale(" + this.count + ")";
      if (this.count <= 1) {
        this.stop();
      }
    }
  },
  rotate: {
    run: 0,
    count: 0,
    flag: false,
    start: function() {
      this.run = setInterval(function() {
        adc.animate.rotate.EXE()
      }, 10);
    },
    stop: function() {
      clearInterval(this.run);
      this.run = this.count = 0;
      this.flag = false;
    },
    EXE: function() {
      if (!this.flag) {
        this.count++;
      } else {
        this.count--;
      }
      if (this.count >= 90) {
        this.flag = true;
      }
      adc.rWrap.style.transform = "rotate(" + this.count + "deg)";
      if (this.count <= 0) {
        this.stop();
      }
    }
  }
}

//Initialization Call
document.addEventListener('DOMContentLoaded', function() {
  adc.init();
});
&#13;
<!DOCTYPE html>
<html>

<head></head>

<body></body>

</html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

Lo-Dash有一个方便的函数叫_.after,它在一定数量的调用后执行一个给定的函数。例如,以下函数仅在完成所有超时后执行。

&#13;
&#13;
var finish = _.after(5, function () {
  console.log('All functions completed!');
});

setTimeout(function () { console.log('A'); finish(); },  500);
setTimeout(function () { console.log('B'); finish(); }, 1000);
setTimeout(function () { console.log('C'); finish(); }, 1500);
setTimeout(function () { console.log('D'); finish(); }, 2000);
setTimeout(function () { console.log('E'); finish(); }, 2500);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
&#13;
&#13;
&#13;

如果您不想包含Lo-Dash,您可以相当轻松地自己实施_.after

function callAfter(n, func) {
  var i = 0;
  return function () {
    if (i < n) { i++; }
    else { return func(); }
  };
}