2017-01-04 1 views
0

Ich versuche Sound und Animation zu diesem "Ping-Pong" (Fizz-Buzz) -Programm hinzuzufügen. Was ich will, ist, dass für jedes Element im Array (Nummer/Ping/Pong/Pingpong) der Text in der Liste eingeblendet wird, während der Sound und die Animation abgespielt werden.Wie koordiniere ich das Timing für Sound und Animation?

Was ich bekomme ist - die ganze Liste blendet alle auf einmal ein, die Sounds spielen alle nacheinander (und wenn die eingegebene Nummer groß ist, geht es für immer weiter), aber die Animation passiert nur einmal (anscheinend für nur die letzte Animation). Das gesamte Projekt befindet sich unter: https://github.com/karenfreemansmith/Epic-AdvancedJSwk1-PingPongCalculator, zusammen mit einem Link zu einer Seite mit dem, was gerade funktioniert. (Ein wenig früher als der Code unten, die es nur auf neue Weise gebrochen.)

Ich habe setInterval und setTimeout versucht, sie alle durch den Aufruf einer Funktion für die Synchronisierung zu verwenden, die zu einem Zeitpunkt ein Element zeigen mit seinem Sound und Animation:

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

und sucht die Funktion wie folgt aus:

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>"); 
    } 
} 

und die Spielfunktionen sind alle im Grunde das gleiche, aber mit verschiedenen Sounds:

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>"); 
} 

Ich denke, ich muss missverstehen, wie die setTimeout funktioniert. Warum wird die Animation nur einmal abgespielt? Und warum gibt es keine Pause zwischen den Elementen, die der Liste hinzugefügt werden?

+0

Siehe [HTML5 Audio-Streaming: präzise Latenz messen?] (Http://StackOverflow.com/Questions/38768375/HTML5-Audio-Streaming-precisely-Measure-Latency/) – guest271314

+0

Ich bin nicht Streaming der Audio, nur Verwenden von MP3-Dateien zum Abspielen von Ping-Pong-Sounds. Es sieht so aus, als ob die Ereignisse hier hauptsächlich prüfen, ob die Datei heruntergeladen wurde oder nicht. – KAS

+0

Das Medium wird abgerufen, dann können 'timeupdate'- oder' progress'-Ereignisse verwendet werden, um '.currentTime' der Medienwiedergabe zu bestimmen, um bestimmte Stile oder Animationen anzuwenden. – guest271314

Antwort

1

Das Problem hier ist, weil, ja, Sie etwas falsch verstehen, wie setTimeout funktioniert.

Was Sie tun, ist es so nennen:

window.setTimeout(playVolley(), 1000); 

was zu sagen, entspricht: „Hey JS, sofort meine Funktion playVolley ausführen (da ich() verwenden, um anzugeben, dass ich möchte es genannt), und DANN in 1000 Sekunden rufen, was auch immer es zurückgegeben hat ".

Was ich stark vermute, Sie wirklich tun wollte, ist:

window.setTimeout(playVolley, 1000); 

Hinweis, wie es keine "()" nach playVolley. Das ist äquivalent zu sagen: "Hey JS, in 1000 Sekunden führe meine coole Funktion namens playVolley" aus.

Wenn "das Übergeben des Funktionsnamens ohne()" für Sie keinen Sinn ergibt, ist das in Ordnung, lesen Sie einfach "Funktionen als erstklassige Objekte" (z. B. here). Die Idee ist einfach jede Funktion ist wirklich wie eine Variable, die eine "Funktion" in sich hat, und Sie können es an alles übernehmen "Funktion als eine Eingabe. Welche, zum Beispiel setTimeout tut - es braucht eine" Funktion "und ein „integer“ eine Auszeit setzen

Aber nur zur Festsetzung dieser wird dir nicht helfen Es gibt ein weiteres Problem hier:..

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

See, hier effektiv Sie output.length Timeouts gesetzt, alle von ihnen auf einmal , in 1000 Sekunden zu feuern.Was sie tun werden - in 1000 werden alle gleichzeitig ausgeführt werden.Also wird alles, was Sie bei der ersten Reparatur beheben werden, dass alle Ihre Animationen und Sounds nicht sofort spielen, sondern nach einer Verzögerung von 1000ms.

Was, ich wieder stark vermuten, Sie wollten tun, ist jeden Schritt output Array eins nach dem anderen, mit 1000 Verzögerung zwischen einander aufzurufen.

Um dies zu erreichen, müssen Sie die Art, wie Sie Ihre Anrufe planen, umgestalten. Anstatt alle auf einmal zu planen, müssen Sie sie verketten. Ein schmutziges, aber einfaches Beispiel wäre ein Index für den aktuellen Animationsschritt, und wenn Ihr playXXX fertig ist, plant es den nächsten Schritt, bis alle Schritte abgeschlossen sind.

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 

Auch dies ist ein sehr schmutziges Beispiel (Globals, eeeew), sag nicht, dass jemand den ich euch gezeigt, aber es kann Ihnen den Einstieg, und wenn Sie einen Dreh Verschlüsse zu bekommen, Sie Ich schreibe es in etwas überschaubares um.

+0

Und ja, Sie könnten auch einige Probleme mit der Audio-Latenz haben, aber ich glaube nicht, dass Sie das wirklich wollen, und sowieso werden Sie darauf achten, wann Sie zu ihnen kommen (in einer neuen Frage, nehme ich an). –

+0

Ich mag die Globals nicht, aber es funktioniert super, danke! – KAS

+0

Ich hasse sie auch, aber es ist der einfachste Weg zu beginnen. Sie können auch einige Closures hinzufügen, um diese Schritte zu kapseln, oder Sie verwenden einige Verkettungsmethoden aus einer Bibliothek, ich nehme an, dass sogar jQuery einige haben muss. Ich bin mit diesen Bibliotheken nicht wirklich vertraut, an einem Tag, an dem ich eine "Async" -Bibliothek benutzt habe, um all diese Sachen zu machen, aber ich habe damals ein paar Mal geblinzelt und die gesamte JS-Landschaft hatte sich verändert. Ich helfe dir dort. –

Verwandte Themen