• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

setTimeout reloaded

austriaman

Mitglied
Hallo,

ok, ich bastle nach wie vor an einer verzwickten setTimeout-Variation und muss gestehen, dass ich mit meinem Latein ein wenig am Ende bin.

Kurze Beschreibung des gewünschten Endresultats:

Gegeben sind eine gewissen Anzahl an (hier exemplarisch 10) Sets von je 3 <DIV>s [mit durchnummerierten IDs: ID_1, ID_2, ID_3, ID_4, ...], die via setTimeout ein-/ bzw. ausgeblendet werden sollen.

Dabei soll <DIV 1> zwei Sekunden lang, <DIV 2> vier Sekunden lang und <DIV 3> eine Sekunde lang angezeigt werden, danach beginnt der Spaß mit dem nächsten Set von Neuem.

Zu dem Thema gibt's im Netz ja schon massig Material - habe daher versucht, ähnliche Problemlösungen auf stackoverflow zu implementieren, bin aber gescheitert.

Meine ursprüngliche [sehr naive] Herangehensweise sah folgendes vor:

Code:
var aktiv = 1; // bestimmt, welches DIV aktiv ist, daher angezeigt werden soll
    var zeit = 0; // bestimmt die Zeitintervalle
   

    var Durchlauf_2s;
    var Durchlauf_4s;
    var Durchlauf_1s;
   
    for (var i=0; i<=9; i++) { // 10 Durchgänge
   
    document.getElementById("ID_" + aktiv).style.display = "block";
    if (aktiv > 1) { // if-Kondition kommt für den ersten Durchlauf nicht zustande, da 1. DIV aktiv ist.
        document.getElementById("ID_" + (aktiv - 1)).style.display = "none";
        }
    aktiv++; // "aktiv" wird auf die nächsthöhere ID gesetzt gesetzt
   
    Durchlauf_2s = setTimeout(function() {
        zeit = zeit + 2000; // nach 0 + 2000, daher nach einem Zeitintervall von 2000 wird das Timeout aktiv
        document.getElementById("ID_" + (aktiv - 1)).style.display = "none";
        document.getElementById("ID_" + aktiv).style.display = "block"; // 
        aktiv++;
    }, zeit)
   
    Durchlauf_4s = setTimeout(function() {
        zeit = zeit + 4000;
        document.getElementById("ID_" + (aktiv - 1)).style.display = "none";
        document.getElementById("ID_" + aktiv).style.display = "block";
        aktiv++;
    }, zeit)
   
    Durchlauf_1s = setTimeout(function() {
    if (aktiv > 1) {
        zeit = zeit + 1000;
        document.getElementById("ID_" + (aktiv - 1)).style.display = "none";
        document.getElementById("ID_" + aktiv).style.display = "block";
        aktiv++;
        }
    }, zeit)
   
    }

Ich bin mir auch durchaus der Problematik der globalen "zeit" Variable bewusst (bzw. glaube ich, das als eines der Probleme identifiziert zu haben) - ich glaube weiters auch richtig verstanden zu haben, dass die for-Schleife den setTimeout-Funktionen "davonläuft", und daher eine Implementierung wie die hier vorgestellte nicht funktionieren und zulässig sein kann.

Nur - wie kriege ich die Sache sonst in den Griff?

Danke an alle ernst gemeinten Hilfestellungen!
LG,
aut.
 
Werbung:
Hatte ich in deinem vorherigen Thread beantwortet. Anstatt der For-Loop Callbacks.
Hallo,
da ich das Forum hier ja nicht sinnlos zumüllen wollte, habe ich mich vorab natürlich auch mit der vorgeschlagenen Callback-Thematik auseinandergesetzt.

Wie bereits erwähnt, ist mir durchaus bewusst, dass der hier von mir gezeigte Code so nicht funktionieren kann. - Ich habe mehrere Problemlösungsansätze (eben auch Callbacks) durchgespielt; fand die hier gepostete Version des Codes für etwaige Engel im Forum aber am einfachsten nachzuvollziehen. :)

Bezüglich Callback:
Leider kann ich nicht ganz nachvollziehen, wie ich statt einer for-Schleife Callbacks einsetzen kann.
Meines Erachtens müsste ein effektiver Code, der Callbacks einsetzt, ungefähr so aussehen (der Einfachkeit halber ohne for-Schleife und mit nur einer setTimeout Funktion):

Code:
var aktiv = 1; // bestimmt, welches DIV aktiv ist, daher angezeigt werden soll
var zeit = 0; // bestimmt die Zeitintervalle
   

var Durchlauf_2s;



function Durchlaeufe(ersterSchritt) {
    ersterSchritt(); // CALLBACK1
}

Durchlaeufe(
    function() {
        document.getElementById("ID_" + aktiv).style.display = "block";
        aktiv++;
        if (aktiv > 1) {
            document.getElementById("ID_" + (aktiv - 1)).style.display = "none";
            }
        function Durchlaeufe2(zweiterSchritt) {
                zweiterSchritt(); // CALLBACK2
        }
        Durchlaeufe2(function() {
            Durchlauf_2s = setTimeout(function() {
                zeit = zeit + 2000;
                document.getElementById("ID_" + (aktiv - 1)).style.display = "none";
                document.getElementById("ID_" + aktiv).style.display = "block"; 
                aktiv++;
            }, zeit)
        })
    }
);

Selbst das funktioniert aber so nicht.

:(
 
Werbung:
Ich würde es so machen:
Code:
function div1display(idx) {
document.getElementById("ID_" + (idx + 2)).style.display = "none";
document.getElementById("ID_" + idx).style.display = "block";
setTimeout(function () { div2display(idx); }, 2000);
}
function div2display(idx) {
document.getElementById("ID_" + idx).style.display = "none";
document.getElementById("ID_" + (idx + 1)).style.display = "block";
setTimeout(function () { div3display(idx); }, 4000);
}
function div3display(idx) {
document.getElementById("ID_" + (idx + 1)).style.display = "none";
document.getElementById("ID_" + (idx + 2)).style.display = "block";
setTimeout(function () { div1display(idx); }, 1000);
}
div1display(1);
Das Starten für alle 10 Sets kannst Du dann in einer for-Schleife erledigen. Man hätte es auch mit nur einer Funktion und entspr. Berechnungen machen können, aber ich finde es so übersichtlicher und leichter lesbar.
 
PS: Hier auch noch eine Version mit nur einer Funktion:
Code:
function divdisplay(groupidx) {
     var times = [2000, 4000, 1000];
     var subidx = -1;
     function divdisp() {
         var previdx = subidx;
         subidx = subidx < 2 ? subidx+1 : 0;
         document.getElementById("ID_" + (groupidx + previdx)).style.display = "none";
         document.getElementById("ID_" + (groupidx + subidx)).style.display = "block";
         setTimeout(divdisp, times[subidx]);
     }
     divdisp();
}
divdisplay(1);
 
Es gibt schönere Patterns, aber hier ist ein einfach nachzuvollziehendes mit jQuery:
Code:
var changeVisibility = function() {
    $('#div1').fadeIn(1000).fadeOut(2000, function() {
        $('#div2').fadeIn(1000).fadeOut(2000, function(){
            $('#div3').fadeIn(1000).fadeOut(2000, function() {
                changeVisibility();
            });
        });
    });
};
changeVisibility();

Die nachfolgende Style-Änderung wird als Callback an die vorhergehende übergeben. Wenn alle durchgelaufen sind, wird die Funktion rekursiv aufgerufen und das Ganze beginnt von vorn.
 
Werbung:
PS: Mir scheint, ich hatte dich falsch verstanden:
danach beginnt der Spaß mit dem nächsten Set von Neuem.
Du willst also nicht, dass sich die Gruppen gleichzeitig ändern, sondern dass sie nacheinander ablaufen. Dann entfällt das mit der for-Schleife natürlich und man muss meine zweite Version wie folgt ändern:
Code:
function divdisplay(idx) {
    var times = [2000, 4000, 1000];
    function divdisp() {
        var previdx = idx;
        idx = idx < 30 ? idx+1 : 1;
        document.getElementById("ID_" + previdx).style.display = "none";
        document.getElementById("ID_" + idx).style.display = "block";
        setTimeout(divdisp, times[(idx-1) % 3]);
    }
    divdisp();
}
divdisplay(-1);
 
Zuletzt bearbeitet von einem Moderator:
@ Tronjer:
Danke für den Vorschlag, allerdings benötige ich gar keine fade-Elemente; generell erscheint mir [auch deshalb] der Einsatz von jquery gar nicht unbedingt notwendig (wäre wohl ein bißchen so wie mit Kanonen auf Spatzen feuern :D ). Auch scheint mir die Problematik des erneuten "Parallelfeuerns" der verschiedenen Sets nicht gelöst (?)

@Sempervivum:
Ich sehe den Code und glaube auch nachvollziehen zu können, wo du damit hinwolltest -
allein, er funktioniert nicht. Nun ist der Fehler aber wahrscheinlich wohl eher bei mir denn bei dir zu suchen, wäre es daher möglich, exemplarisch darzulegen, wie der Code [in welchem Umfeld] implementiert werden könnte?

Danke,
aut.


Nochmals kurz und prägnant die Aufgabenstellung [sollte ich mich diesbezüglich missverständlich ausgedrückt haben, so tut mir das leid!]:

SET 1:
DIV_1 [-]
DIV_2 [2 Sekunden nach DIV_1]
DIV_3 [4 Sekunden nach DIV_2]

SET2:
DIV_4 [1 Sekunde nach DIV_3]
DIV_5 [2 Sekunden nach DIV_4]
DIV_6 [4 Sekunden nach DIV_5]

SET3:
DIV_7 [1 Sekunden nach DIV_6]
DIV_8 [2 Sekunden nach DIV_7]
DIV_9 [4 Sekunden nack DIV_8]

// ETC.
 
Zuletzt bearbeitet:
Nun ist der Fehler aber wahrscheinlich wohl eher bei mir denn bei dir zu suchen
Dein Vertrauen ehrt mich, allerdings hatte ich die dritte Version nicht getestet und sie war noch fehlerhat. So ist es richtig:
Code:
(function() {
     idx = 0;
     var times = [2000, 4000, 1000];
     function divdisp() {
         var previdx = idx;
         idx = idx < 30 ? idx+1 : 1;
         if (previdx > 0) document.getElementById("ID_" + previdx).style.display = "none";
         document.getElementById("ID_" + idx).style.display = "block";
         setTimeout(divdisp, times[(idx-1) % 3]);
     }
     divdisp();
})();
 
Werbung:
Hallo,
danke für die Korrektur! *THUMBS_UP*

Funktioniert reibungslos.

Nun muss das Timeout mit dem letzten DIV (in unserem Falle DIV_30) nur mehr stoppen.

Ich habe deinen Code diesbezüglich [offensichtlich außerordentlich stümperhaft] zu adaptieren versucht, mit dem Ergebnis, dass nach dem letzten DIV einfach gar nichts mehr angezeigt wird:

So wurde aus deinem vorgeschlagenen
Code:
idx = idx < 30 ? idx+1 : 1;
mein
Code:
idx = idx < 30 ? idx+1 : clearTimeout(divdisp);
bzw. der ganze Code:

Code:
function() {
     idx = 0;
     var times = [2000, 4000, 1000];
     function divdisp() {
         var previdx = idx;
         idx = idx < 30 ? idx+1 : clearTimeout(divdisp); //  wenn idx unter 30, dann idx+1, sonst clearTimeout
         if (previdx > 0) document.getElementById("ID_" + previdx).style.display = "none";
         document.getElementById("ID_" + idx).style.display = "block";
         setTimeout(divdisp, times[(idx-1) % 3]);
       
     }
     divdisp();
}

Ich bitte hier um ein letztes Mal um deinen fachmännischen Rat,
Grüße aus dem Süden,
aut.
 
Nein, so kann es nicht funktionieren, weil zu dem Zeitpunkt, wo Du den Timer löschst, gar keiner aktiv ist. Probiers mal so:
Code:
function() {
     idx = 0;
     var times = [2000, 4000, 1000];
     function divdisp() {
         var previdx = idx;
         idx++;
         if (previdx > 0) document.getElementById("ID_" + previdx).style.display = "none";
         document.getElementById("ID_" + idx).style.display = "block";
         if (idx < 30) setTimeout(divdisp, times[(idx-1) % 3]);      
     }
     divdisp();
}
 
Nein, so kann es nicht funktionieren, weil zu dem Zeitpunkt, wo Du den Timer löschst, gar keiner aktiv ist. (...)[/code]

Klingt auch wieder einleuchtend.

---

<ASIDE>
...gönne mir gerade ein Gläschen Whiskey on the rocks, beim nächsten Schluck erhebe ich das Glas auf dich!
</ASIDE>
 
Zuletzt bearbeitet:
Werbung:
Zurück
Oben