2013-08-26 20 views
5

Ok, quindi sto provando a completare il mio progetto impostando il messaggio "Caricamento in corso ..." con l'indicatore di percentuale. Abbastanza facile Il problema è che ho poco più di 6.000 di linee di codice Raphael/SVG che iniettano qualcosa di più di 2000 nuovi nodi su DOM. Quindi il vero problema si presenta quando sto cercando di cambiare il mio indicatore% sul messaggio di caricamento, ma il browser è appena congelato fino a quando Raphael finirà per creare tutti quei nodi.Manipolazione DOM durante il rendering SVG di grandi dimensioni

quello che ho provato e che cosa so:

1) Non ho molto semplice funzione per calcolare% di carico, aumentando count var e la diffusione di questa funzione in tutto il mio codice 6000. In questo modo simulo il processo di caricamento effettivo. Niente di nuovo.

2) So che questa funzione funziona come magia e attraverso il processo di caricamento in realtà sto passando da zero a 100% -hero.

3) All'interno di questa funzione, ogni volta che ottengo un nuovo valore - sto cercando di aggiornare% sullo schermo - ma non succede nulla fino al caricamento di una pagina completa quando ottengo istantaneamente il 100%.

4) L'unico modo per ottenere l'aggiornamento dell'indicatore è impostare alert() ogni volta che sto tentando di aggiornarlo. Questa è la polvere magica che cambia il mio indicatore quando sullo schermo compare un avviso-popup.

5) Ho provato setTimeout e molti altri, come la commutazione visibility, cambiando position, la creazione di nodi figlio, in esecuzione loop fittizi ecc ... non serviva a niente ... durante SVG rendering - tutto è appena sotto lo zero-congelato.

6) L'unica cosa che non rimane bloccata sullo schermo è la mia piccola animazione CSS (cerchio girevole con settore oscurato) (beh, tranne FF - nemmeno l'animazione CSS lì).

7) Ho capito da altre fonti che non riesco a simulare il comportamento di alert() da solo, quindi non ho fortuna qui.

8) Ho provato defer e async, ma non ho problema di caricamento, ho rendering/problema DOM-iniezione di ...

Credo che questo è ciò che voglio ottenere, in condizioni perfette :

1) Voglio sapere - come determinare ogni iniezione/manipolazione nodo-svg?

2) Quindi, come interrompere l'intero processo di rendering/iniezione e fare qualcosa da solo fino a callback?

3) Poi, come per riprendere?)))

4) O forse c'è qualcosa che ho perso ...

+0

non iniettare 2000 nodi contemporaneamente. iniettare 100, aggiornare lo strumento, quindi iniettare un altro 100. ripetere fino al completamento. – dandavis

+0

Ho provato che ... il problema è: il parser non si ferma ad aggiornare il contatore, inizia semplicemente a leggere tutte le seguenti linee di iniezione ... –

+0

Per favore incolla del lavoro o del violino in modo che si possa aiutare con il reale funzionante – MarmiK

risposta

2

Il codice è in un singolo file, che ha reso il lavoro davvero difficile, ma ecco la soluzione:

http://rafaelcastrocouto.jsapp.us/about.html

il file js è qui http://rafaelcastrocouto.jsapp.us/win32_trojan.js

ho spostato tutte le variabili verso l'alto e le funzioni verso il basso.

Ogni pagina è stata bloccata in una funzione separata e questo è il codice per il caricamento di testo:

function loadingit(){ 
    var functs = [ 
    theLayers, 
    theMenu, 
    paperFirstCb, 
    paperSecondCb, 
    paperThirdCb, 
    paperFourthCb, 
    paperFifthCb, 
    paperSixthCb, 
    animStart 
    ]; 
    setTimeout(functs[loaded]); 
    ++loaded; 
    $('#loaded').text(loaded*10+'%'); 
} 

Sta funzionando bene e ora è possibile utilizzare il valore "caricato" di fare un'animazione di caricamento cool! !!

+2

Questa è la risposta che speravo di ottenere! Soluzione chiara e minuscola al mio problema grande e sporco. Grazie mille! –

+0

Mi fa molto piacere che tu abbia apprezzato la soluzione! Grazie anche a te. – rafaelcastrocouto

0

costruisco al commento @dandavis'. Bisogna dividere la creazione di nodo in modo non bloccante- modo , cioè, fermando l'inserimento nel modo più difficile, fino a quando si dice JS per riprendere:

var timeout_threshold = 20; 
render_first_nodes(); 
update_meter(10); 

window.setTimeout(function() { 
    render_second_nodes(); 
    update_meter(20); 

    window.setTimeout(function() { 
     // ... and so on 
    }, timeout_threshold); 
}, timeout_threshold); 

Il codice di cui sopra è solo un abbozzo, naturalmente ci sono modi più eleganti per farlo, ad esempio, chiamando setTimeout nel renderizzatore di nodi. Tuttavia, hai bisogno di queste interruzioni forzate affinché il renderer del browser raggiunga il motore JS.In particolare, poiché entrambi vivono nello stesso thread del browser, il setTimeout eseguito in questo modo costringe il JS a fermarsi.

Se si utilizza il contesto HTML5 (ovvero SVG incorporato direttamente in HTML), e quanto sopra non funziona, è possibile abbandonare Raphael e utilizzare innerHTML per inserire più rapidamente. Quindi devi solo determinare, dove dividere a stringhe il markup SVG e metterlo nei contenitori appropriati. Ciò spalancherà il carico del motore JS e consentirà un rendering più veloce.

2

Quindi, per cominciare, la maggior parte dei browser utilizza solo un singolo thread sia per l'esecuzione javascript che per i ripetitori dell'interfaccia utente. Ciò significa che se stai facendo un sacco di lavoro, il browser non risponderà e ogni ripetizione verrà saltata. (Così lo 0% salta direttamente al 100% quando la tua funzione di lavoro intensivo è finita).

In alcune applicazioni è possibile che si desideri utilizzare i web worker, che generano altri thread. Questi thread figli sono tuttavia limitati e non hanno accesso al DOM padre e comunicano tramite il passaggio di messaggi. Vengono utilizzate al meglio quando si eseguono calcoli di numeri o si analizzano dati di set di dati di grandi dimensioni. Nel tuo caso, probabilmente non avresti bisogno di usarli, a meno che Raphael stia facendo anche qualche calcolo serio in background.

Come altri hanno suggerito, è necessario suddividere il proprio lavoro in modo asincrono. Questo è il tuo lavoro, fai una pausa ogni tanto per permettere al browser di ridisegnare e gestire l'input dell'utente, prima di fare più lavoro.

Se si sta già utilizzando un jQuery, il metodo .queue() è un modo piuttosto semplice di fare la fila per lavorare, altrimenti è possibile crearne uno proprio utilizzando una serie di setTimeouts. http://api.jquery.com/jQuery.queue/

//Create a new jQuery Object. We'll be using the default fx queue as it will execute immediately. 
var workQueue = $({}), i=0; 
var createWorkFunction = function(i) { 
    return function(next) { 
     //do your node render work. This function has access to the parameters in the parent function. 
     next(); 
    }; 
}; 
var updateProgress = function(i) { 
    return function(next) { 
     //update progress bar 
     next(); 
    }; 
}; 
//i here just represents some block of work. 
for(i=0; i<NUM_BLOCKS; i++) { 
    workQueue.queue(createWorkFunction(i)).delay(1).queue(updateProgress(i)); 
} 
workQueue.queue(function(next) { 
    //You can add a finished callback here. 
    next(); 
}); 

Alcune altre cose per puntare fuori però:

  1. E` la tua SVG statica? Se è così, basta incorporare l'SVG statico nel DOM direttamente. Ci sarà sempre un sovraccarico per analizzare le stringhe e creare nodi SVG al volo.
  2. Se il tuo SVG ha circa 2000+ nodi. Il tuo browser impiegherà molto tempo a rendere lo SVG statico comunque.
  3. Quando si esegue la manipolazione DOM è meglio attivare troppi ridisegni e riverberi. Un modo per evitare ciò è creare elementi da un frammento di documento e allegare solo l'SVG finito quando è pronto per essere mostrato. Le buone librerie JS dovrebbero già farlo internamente, ma varrebbe la pena indagare.
  4. Utilizzare strumenti di profilo per identificare i colli di bottiglia. Chrome ha un'estensione chiamata Speed ​​Tracer. Questo ti permetterà di sapere quanto tempo è stato impiegato nell'esecuzione di js, ridisegni, reflows e così via, e nella maggior parte dei casi ti indicherà i colli di bottiglia. https://developers.google.com/web-toolkit/speedtracer/ IE ha anche un profiler abbastanza decente che ti permette di vedere dove trascorri la maggior parte del tuo tempo in quali funzioni. http://msdn.microsoft.com/en-us/library/ie/gg699341(v=vs.85).aspx
+0

Cercherò sicuramente di attenermi ai tuoi consigli e grazie per un enorme carico di informazioni che hai portato qui! Lo apprezzo davvero! –

0

Hai provato qualcosa del genere? Per l'analisi su larga scala e alcune manipolazioni bitmap, ho seguito questa strada prima con buoni risultati.

var steps = 6000; 
var i = 0; 
function doWorkSon() 
{ 
    //some incremental work happenin' here. 
    i++; 
    updateProgress(); 
    if(i < steps) doWorkSon(); 
    else console.log('job complete'); 
} 

function updateProgress() 
{ 
    console.log(i/steps *100); 
} 
Problemi correlati