2009-07-30 21 views
5

Ho creato uno script che dissolve il colore di sfondo di un elemento. Uso setTimeout() per apportare una modifica incrementale al colore ogni 5 ms. La sceneggiatura funziona alla grande se sto solo sbiadendo il colore di sfondo di una cosa alla volta, ma se ho, diciamo, 50 elementi che sto sbiadendo tutti contemporaneamente, la velocità è molto più lenta di 5 ms a causa di tutti il simultaneo setTimeout() s in esecuzione in una volta. Una dissolvenza che normalmente dovrebbe essere eseguita in 1 secondo, ad esempio, potrebbe richiedere 30 secondi se sto sbiadendo 50 elementi alla volta.JavaScript setTimeout() rallenta sotto carico intenso

Qualche idea su come posso superare questo?

Ecco lo script nel caso in cui qualcuno ha un idee:

function fadeBackground(elementId, start, end, time) { 
    var iterations = Math.round(time/5); 

    var step = new Array(3); 

    step[0] = (end[0] - start[0])/iterations; 
    step[1] = (end[1] - start[1])/iterations; 
    step[2] = (end[2] - start[2])/iterations; 

    stepFade(elementId, start, step, end, iterations); 
} 

function stepFade(elementId, cur, step, end, iterationsLeft) { 
    iterationsLeft--; 

    document.getElementById(elementId).style.backgroundColor 
     = "rgb(" + cur[0] + "," + cur[1] + "," + cur[2] + ")"; 

    cur[0] = Math.round(end[0] - step[0] * iterationsLeft); 
    cur[1] = Math.round(end[1] - step[1] * iterationsLeft); 
    cur[2] = Math.round(end[2] - step[2] * iterationsLeft); 

    if (iterationsLeft > 1) { 
     setTimeout(function() { 
      stepFade(elementId, cur, step, end, iterationsLeft); 
     }, 5); 
    } 
    else { 
     document.getElementById(elementId).style.backgroundColor 
      = "rgb(" + end[0] + "," + end[1] + "," + end[2] + ")"; 
    } 
} 

E 'usato in questo modo:

fadeBackground("myList", [98,180,232], [255,255,255], 1000); 

risposta

11

Ecco un article da parte di Google in cui l'autore discute il loro lavoro sul timer per Gmail. Hanno scoperto che avere un singolo timer ad alta frequenza era più veloce rispetto all'utilizzo di timer multipli se avevano un utilizzo temporizzato pesante e rapido.

Si potrebbe avere un timer che scatta ogni 5 ms e aggiungere tutti gli elementi che devono essere sbiaditi in una struttura dati che tiene traccia di dove si trovano nel processo di dissolvenza. Quindi il tuo timer singolo può guardare attraverso quella lista ed eseguire la prossima dissolvenza per ogni elemento ogni volta che viene attivato.

D'altra parte, hai provato a utilizzare una libreria come Mootools o JQuery invece di ruotare il tuo framework di animazione? I loro sviluppatori hanno lavorato molto per ottimizzare questo tipo di operazioni.

+0

Stavo pensando che un timer potrebbe essere la strada da percorrere, ma ho temuto di dover implementare la modifica. :) In realtà ho deciso di lanciare da solo perché stavo usando jQuery per animare() e non è riuscito a svanire in realtà circa il 10% delle volte. Sfortunatamente, questo è un tasso di errore inaccettabile. Controllerò l'articolo. Grazie mille! – core

+0

Heh. Stackoverflow ha anche il problema "non riesce ad animare". – Nosredna

4

Prima di tutto lo script non tiene conto del fatto che il timeout minimo di solito è di 10-15 ms a seconda del browser. Puoi vedere my post on this topic. All'interno troverai una tabella per i browser più diffusi e un link al programma che lo misura, così puoi verificare tu stesso il reclamo. Mi dispiace dirlo, ma le iterazioni ogni 5 ms sono un pio desiderio.

In secondo luogo, i timer non sono interruzioni. Non c'è magia in loro — non possono interrompere ciò che è in esecuzione nel browser ed eseguire il loro carico utile. Invece verranno rimandati fino al termine del codice di esecuzione e il browser riprende il controllo e la possibilità di eseguire i timer. La dissolvenza di 50 elementi richiede tempo e scommetto che è più di 5 ms, soprattutto se si prende in considerazione l'intero modello differito del browser: si aggiorna DOM, e il browser aggiornerà la sua rappresentazione visiva e hellip; ad un certo punto nel tempo.

voglio finire con una nota positiva:

  • Invece di dissolvenza 50 singoli elementi, cercare di raggrupparli e fade loro genitori — può essere più veloce.
  • Sii più creativo nell'interfaccia utente. Cerca di trovare una soluzione, che non richieda la dissolvenza di molti elementi indipendenti contemporaneamente.
  • Verificare sempre che le ipotesi di sfondo siano corrette prima di progettarle intorno.
  • Se possibile, prova a scegliere come target i browser moderni. Dalla mia esperienza personale, Google Chrome è molto bravo con i timer e il suo motore JavaScript (V8) è estremamente veloce.
Problemi correlati