如何协调声音和动画的时间

时间:2017-01-04 23:04:52

标签: javascript animation audio settimeout setinterval

我试图为这个" ping-pong"添加声音和动画。 (fizz-buzz)节目。我想要发生的是对于数组中的每个项目(数字/ ping / pong / pingpong),文本在声音和动画播放时淡入列表。

我得到的是 - 整个列表一下子全部消失,声音一次播放一次(如果输入的数字很大,它会一直播放)但动画只发生一次(显然只是最后一个动画。)

整个项目位于:https://github.com/karenfreemansmith/Epic-AdvancedJSwk1-PingPongCalculator,以及指向当前正在运行的页面的链接。 (略低于下面的代码,它只是以新的方式打破了它。)

我一直在尝试使用setInterval和setTimeout通过调用一个函数来同步它们,该函数将使用它的声音和动画一次显示一个元素:

var play=setInterval(function() {
  var i=1;
  output.forEach(item => {
    showNext(item);
    if(i>=output.length) {
      clearInterval(play);
    }
    i++;
  });
}, 1000);

功能如下:

function showNext(item) {
  acorn.style.animation= "";
  acorn.style.webkitAnimation="";
  if(item==="ping") {
    window.setTimeout(playPing(), 1000);
  } else if(item==="pong") {
    window.setTimeout(playPong(), 1000);
  } else if(item==="ping-pong") {
    window.setTimeout(playVolley(), 1000);
  } else {
    window.setTimeout(playMiss(), 1000);
    $("#pingpong").append("<p class='"+item+"'>" + item + "</p>");
  }
}

并且播放功能基本相同,但声音不同:

function playPing() {
  acorn.style.animation= "ping 1s linear";
  acorn.style.webkitAnimation="ping 1s linear";
  sndSlam1.currentTime = 0;
  sndSlam1.play();
  $("#pingpong").append("<p class='ping'>ping</p>");
}

我认为我必须误解setTimeout是如何工作的。为什么动画只播放一次?为什么要添加到列表中的元素之间没有暂停?

1 个答案:

答案 0 :(得分:1)

这里的问题是因为,是的,你稍微误解了setTimeout的工作原理。

你所做的就是这样称呼:

window.setTimeout(playVolley(), 1000);

这相当于说:&#34;嘿JS,马上执行我的函数playVolley(因为我使用()来指定我想要它被调用),然后在1000秒内调用任何东西它已经返回&#34;。

我强烈怀疑,你真的想做的是:

window.setTimeout(playVolley, 1000);

注意没有&#34;()&#34;玩完游戏后。这相当于说:&#34;嘿JS,在1000秒内执行我的酷函数playVolley&#34;。

如果&#34;传递函数名称而没有()&#34;没有意义,没关系,只需阅读&#34;作为头等对象的功能&#34; (例如,here)。这个想法就是任何函数都非常像一个包含&#34;函数的变量。在它中,您可以将它传递给任何需要&#34;作为输入。例如,setTimeout就是这样 - 它需要一个&#34;功能&#34;和一个&#34;整数&#34;设置超时。

但只有解决这个问题才能帮到你。这里还有另一个问题:

output.forEach(item => {
  showNext(item);
  ...
}

请参阅此处,您有效地设置output.length超时,所有一次,以1000秒内触发。他们将做什么 - 在1000年他们将同时执行。所以你在第一次修复时所做的就是你所有的动画和声音不会立即播放,但是在1000ms延迟之后。

我再次强烈怀疑,你想要做的是逐个调用output数组的每一步,彼此之间有1000个延迟。

要实现这一目标,您需要重构您安排通话的方式。您不需要一次性安排它们,而是需要将它们链接起来。一个肮脏但简单的例子就是为当前动画步骤建立一个索引,当你的playXXX完成时,它会安排下一步运行,直到完成所有步骤。

var currentAnimationStep = 0;
var output = ["ping", "pong", "ping", "pong"];

snowNext(output[currentAnimationStep]);

function showNext(item) {
+  if (item === undefined) {
+    return;
+  }
+
  ...
}

function playPing() {
  acorn.style.animation= "ping 1s linear";
  acorn.style.webkitAnimation="ping 1s linear";
  sndSlam1.currentTime = 0;
  sndSlam1.play();
  $("#pingpong").append("<p class='ping'>ping</p>");

+ currentAnimationStep += 1;
+ showNext(output[currentAnimationStep]);
}

// All other playXXX functions will need the same call added

再一次,这是一个非常肮脏的例子(全局,eeeew),不要告诉任何人我告诉你这个,但它可以让你开始,当你得到一个关闭的挂钩,你和&# #39;将其重写为更易于管理的内容。