2016-03-21 5 views
1

Seit einiger Zeit erneut auszulösen bereits mit folgendem Code ich bin zu kämpfen:Wie eine Funktion mit Timeouts über Tasteneingabe

$(document).ready(function(){ 
    keyBind(); 
}); 
var set = []; 
var start = 0; 
var total = 3; 
var timeout = 1000; 
function displayImages(i, total){ 
    var pixBox = $('#picture-box'); 
    var imgPre = 'resources/exhibit-'; 
    var imgExt = '.png'; 
    var sndExt = '.wav'; 
    var imgSrc = '<img class="image" src="' + imgPre + i + imgExt +'">'; 
    var sndSrc = new Audio(imgPre + i + sndExt); 
    var magic = ((i+1)%total) + ',' + total; 

    sndSrc.play(); 
    pixBox.append(imgSrc); 

    var sT = setTimeout('displayImages(' + magic + ')', timeout); 
    set.push(sT); 

    if(sT >= total+1){ 
     sndSrc.pause(); 
    } 
    if(sT === total+1){  
     clearTimeout(sT);    
     // $('img').remove(); 
     $('img:not(:last-child)').remove(); 
    } 
    return false; 
} 
function keyBind(){ 
    $(document).keydown(function(e) { 
     switch (e.which) { 
      case 75: //k 
       displayImages(start, total); 
       break; 
      case 80: //p 
       clearTimeout(set); 
       break; 
      default: 
       return; 
     } 
     e.preventDefault(); 
    }); 
} 

Es ist eine Art von sehr primitiv Diashow mit für jedes Bild/Dia-Sound-Dateien zu begleiten. Wie Sie sehen können, wird es durch Tastatureingabe gesteuert (keyBind Funktion). Und alles funktioniert gut, aber nur zum ersten Mal. Wenn ich es triggere, timeOut Funktion macht es Job und beide if Anweisungen (zuerst verantwortlich für den Ton nach der letzten Datei schneiden, zweitens verantwortlich für das Wrapping Bilder zurück auf das erste nach dem letzten angezeigt wird) brennen und alles ist gut.

Das heißt, bis ich die Sequenz neu starten möchte, ohne zu aktualisieren. Wenn ich das tue, werden Sounddateien stumm und die Bildsequenz wird zu einer Endlosschleife.

Ich habe bereits versucht, Anfang und Ende der Sequenz in separaten Funktionen zu trennen, ich habe versucht, das Div zu löschen und den Sound am Anfang der Sequenz zurückzusetzen, und ich habe versucht, die timeOut auch am Anfang zurückgesetzt. Alles vergebens. Haben Sie, liebe und gute Leute von SO, eine Ahnung, was mit meinem Code nicht stimmt, und können Sie etwas Licht darauf werfen? Es wird ein Lebensretter sein.

EDIT

Es sieht aus wie setTimeout(sT) funktioniert nicht. Ich habe eine console.log hinter ihm und sT ist nicht 0, es hat immer noch ID der letzten Iteration. Was könnte die Ursache sein? Was mache ich falsch?

Antwort

1

Einige Fragen:

Sie den Wert verwenden, dass setTimeout zurückkehrt, als ob es einen Sinn (inkrementell) hat, aber der Istwert implementierungsabhängig. Sie sollten es nur für sie zu clearTimeout, aber nicht für Dinge wie die folgenden verwenden vorbei:

if(sT >= total+1) 

Es ist auch nicht klar, warum sie an den set Array hinzufügen möchte, als nur die letzte wirklich aussteht. Alle anderen sind bereits abgelaufen, da Sie "chain" an setTimeout anrufen.

Sie löschen sofort nach dem Einstellen eine Zeitüberschreitung, während Sie bei der Einstellung nichts wissen. Warum also nicht die setTimeout vermeiden, wenn Sie direkt danach clearen würden? Das Argument clearTimeout sollte auch eine Zahl sein. Es kann kein Array wie gesetzt sein:

 case 80: //p 
      clearTimeout(set); 

Sie haben eine Start Variable, aber es ignorieren, wenn (i+1)%total tun.

Obwohl kein Problem hier, sollten Sie vermeiden, Strings als Argumente zu setTimeout zu verwenden, da es genauso böse ist wie eval auf diese Weise.

Hier ist eine Version des Codes, der diese Probleme mehrere behebt:

$(document).ready(function(){ 
    keyBind(); 
}); 

var sT = -1; 
var total = 3; 
var timeout = 1000; 

function displayImages(i){ 
    var pixBox = $('#picture-box'); 
    var imgPre = 'resources/exhibit-'; 
    var imgExt = '.png'; 
    var sndExt = '.wav'; 
    var imgSrc = '<img class="image" src="' + imgPre + i + imgExt +'">'; 
    var sndSrc = new Audio(imgPre + i + sndExt); 
    i = (i+1)%total; 

    sndSrc.play(); 
    pixBox.append(imgSrc); 

    if(i == 0){ 
     sT = -1; 
     sndSrc.pause(); 
     $('img:not(:last-child)').remove(); 
    } else { 
     sT = setTimeout(displayImages.bind(null, i), timeout); 
    } 
    return false; 
} 

function keyBind(){ 
    $(document).keydown(function(e) { 
     switch (e.which) { 
      case 75: //k 
       displayImages(0); 
       break; 
      case 80: //p 
       clearTimeout(sT); 
       break; 
      default: 
       return; 
     } 
     e.preventDefault(); 
    }); 
} 

Ich bin nicht ganz sicher, wenn Sie wollen tatsächlich den Ton zu stoppen und die Bilder entfernen (mit einer Ausnahme). Sie müssen diesen Code möglicherweise noch etwas ändern.

+0

Ja, ich habe dieses Ding mit Array alleine erfunden. TBH Ich weiß nicht woher solche Ideen kommen. Aber es ist passiert. Aber das ist unbedeutend. Hauptsache ist DANKE! Tweaked es ein bisschen und es funktioniert wie ein Charme. Sie, mein Herr, sind fantastisch! – roonroon

0

BEARBEITEN: Angepasst gemäß dem korrigierenden Kommentar unten: Sie sollten Argumente nicht direkt mit settimeout an eine Funktion übergeben. Das hat mich mehrere Male gestört. Sehen Sie diese alte Post für eine Lösung zu diesem Teil des Codes: How can I pass a parameter to a setTimeout() callback?

+1

Die Art, wie das OP sie passierte, funktioniert tatsächlich, obwohl es nicht empfohlen wird. – trincot