CSS-Übergänge durch JavaScript blockiert
Ich versuche, eine Ladeleiste während einer sehr intensiven Phase von JavaScript zu erstellen, in der einige ziemlich schwere 3D-Arrays erstellt und gefüllt werden. Diese Ladeleiste muss leer bleiben, bis der Benutzer auf einen Button klickt.
Das Einfrieren tritt auf, egal ob ich -webkit-transition benutze oder nicht (Diese App kann nur für Chrome sein, Cross-Browser ist in meinem Fall nicht notwendig).
Auf der Suche nach Einfachheit habe ich meine Bar so gebaut...
<div id="loader">
<div id="thumb">
</div>
</div>
... und versuchte dann, diese Anzeige in verschiedenen Phasen meiner Haupt-for-Schleife zu erhöhen:
for(i = 0; i < 5 ; i++){
document.getElementById('thumb').style.width = i*25 + '%';
//More Code
}
Das Problem ist, dass alles einfriert, bis das JavaScript abgeschlossen ist. Ich habe eine ähnliche Frage auf Stack Overflow gefunden: "CSS-Animationen verwenden, während JavaScript berechnet", und in den Kommentaren Folgendes gefunden, in Betracht gezogen und/oder ausprobiert:
Web-Arbeiter
Ich denke nicht, dass es funktionieren wird, da mein Skript ein Array mit Objekten und Konstruktoren füllt, die Funktionen enthalten, von denen laut dieser Seite gesagt wird, dass sie nicht funktionieren werden.
jQuery
Keine Option, ich kann in meiner App keine externen Bibliotheken verwenden - in jedem Fall scheint es irgendwie übertrieben, nur für eine Ladeleiste eine ganze Bibliothek zu importieren...
Schlüsselbilder
Das war vielversprechend und ich habe es ausprobiert, aber am Ende friert es auch ein, also keine Freude
timeOut()sDaran gedacht, aber da der Zweck der Ladeleiste darin besteht, Frustration zu verringern, scheint es kontraproduktiv zu sein, die Wartezeit zu erhöhen.
Ich würde mich freuen, jede irgendeine Erhöhung der Leiste in diesem Stadium zu haben, auch wenn sie nicht glatt ist! Ich bin mir ziemlich sicher, dass dies ein Problem ist, das nicht nur mich betroffen hat - vielleicht hat jemand eine interessante Lösung?
P.S.: Ich poste dies als neue Frage anstatt zur referenzierten Frage hinzuzufügen, da ich speziell Hilfe mit JavaScript (nicht jQuery) suche und es vorziehen würde, wenn ich es mit einer Transition (!= Animation) auf der Breite erhalten könnte.
Antwort #1
Einige Leute haben bereits erwähnt, dass du Timeouts verwenden solltest. Das ist der richtige Ansatz, weil es dem Browser Zeit gibt, „durchzuatmen“ und deine Fortschrittsanzeige während der Aufgabe zu rendern.
Du musst deinen Code aufteilen, um asynchron zu arbeiten. Angenommen, du hast derzeit so etwas wie dies:
function doAllTheWork() {
for(var i = 0; i < reallyBigNumberOfIterations; i++) {
processorIntensiveTask(i);
}
}
Dann müssen Sie es in etwas wie dieses verwandeln:
var i = 0;
function doSomeWork() {
var startTime = Date.now();
while(i < reallyBigNumberOfIterations && (Date.now() - startTime) < 30) {
processorIntensiveTask(i);
i++;
}
if(i < reallyBigNumberOfIterations) {
// Here you update the progress bar
incrementBar(i / reallyBigNumberOfIterations);
// Schedule a timeout to continue working on the heavy task
setTimeout(doSomeWork, 50);
}
else {
taskFinished();
}
}
function incrementBar(fraction) {
console.log(Math.round(fraction * 100) + ' percent done');
}
function taskFinished() { console.log('Done!'); }
doSomeWork();
Beachten Sie den Ausdruck (Date.now() - startTime) < 30. Das bedeutet, dass die Schleife so viel wie möglich in einem Zeitraum von 30 Millisekunden erledigen wird. Sie können diese Zahl größer machen, aber alles über 100 ms (im Wesentlichen 10 Bilder pro Sekunde) wird aus der Sicht des Benutzers langsam wirken.
Es mag zutreffen, dass die Gesamtaufgabe mit diesem Ansatz etwas länger dauert als mit der synchronen Version. Aus Sicht des Benutzers ist es jedoch besser, eine Anzeige zu haben, dass etwas geschieht, als unendlich zu warten, während nichts zu passieren scheint - selbst wenn die Wartezeit letzteren kürzer ist.
Antwort #2
Haben Sie versucht, es noch einfacher zu gestalten und eine Funktion zu erstellen, sagen wir:
Pseudonym :
Function increment_bar(amount = 10)
{
document.getElementById('thumb').style.width = i*amount + '%';
}
Dann rufst du von überall, wo du deine Verarbeitung durchführst, einfach diese Funktion alle x Sekunden oder immer dann auf, wenn du einen bestimmten Punkt in der Verarbeitung erreichst (sagen wir 10-20% Abschluss?)
Pseudonym :
{
Doing_work_here;
increment_bar(25);
LOOP
}
