2013-10-19 15 views
5

Sto provando a generare più grafici in un PDF utilizzando Google Charts. Per i PDF, sto usando CakePDF con il motore Wkhtmltopdf. Sembra che stia avendo un problema con il caricamento effettivo del codice di Google Chart nel PDF. Questo è il mio codice attuale per il mio Javascript.Google Charts non funziona con Wkhtmltopdf

<script type="text/javascript" src="https://www.google.com/jsapi"> 
</script> 
<script type="text/javascript"> 
google.load('visualization', '1.0', {'packages':['corechart']}); 
//setTimeout(function() {google.load('visualization', '1.0', {'packages':['corechart']});}, 100); 
google.setOnLoadCallback(drawChart); 
function drawChart(doIt,taken, total, element) 
{ 
    if (typeof doIt === 'boolean') 
    { 
     var data = new google.visualization.DataTable(); 
     data.addColumn('string', 'Type'); 
     data.addColumn('number', 'Courses'); 
     data.addRows([ 
      ['Taken', taken], 
      ['Remaining', total - taken] 
     ]); 
     var options = { 
         'width':40, 
         'height':40}; 
     var chart = new google.visualization.PieChart(document.getElementById(element)); 
     chart.draw(data, options); 
    } 
} 
</script> 

Il problema è che quando faccio la google.load per il pacchetto di visualizzazione, che provoca wkhtmltopdf di tornare con un errore che dice che il motore ha restituito alcun dato. Ho trovato un problema che pensavo fosse simile a Why does google.load cause my page to go blank? quindi ho provato a fare setTimeout (function() {google.load ('visualizzazione', '1.0', {'pacchetti': ['corechart']});}, 100); Il problema con questa soluzione era che se il ritardo era troppo basso, la pagina tornerà senza errori, ma sarà completamente vuota; tuttavia, se ho impostato il ritardo troppo elevato, la pagina sarà solo non caricare il pacchetto ed il Javascript si romperà a

var data = new google.visualization.DataTable(); 

quando chiamo la funzione. Inoltre, il poster ha indicato un problema con document.write(), ma non ho alcun problema se aggiungo le righe document.write() prima o dopo aver aggiunto il contenuto alla pagina. Lo apprezzerei se qualcuno sapesse come far funzionare Google Charts con Wkhtmltopdf e potrebbe aiutarmi.


Ok, Nel tentativo di dare l'API più tempo per caricare, ho spostato dove chiamo la funzione alla fine del PSP. Ora imposta semplicemente una serie di elementi che richiedono grafici disegnati in essi e i valori appropriati, quindi chiama la funzione con il valore degli array. Non sono sicuro di quale sia il problema ora perché si sta rompendo su chart.draw(data, options); ora. Sembra che stia ottenendo i valori corretti e l'elemento passato ad esso però.

Questo sembrerà davvero tondo poiché lo è. Per qualsiasi motivo, Wkhtmltopdf non può leggere nulla che ho inserito in un tag javascript. Ho provato tutto quello che posso per farlo leggere, ma non lo farà. Il plugin CakePDF può leggere Javascript, quindi il mio codice JS è nel layout PDF predefinito. Quindi nella vista effettiva resa da WkhtmltoPdf, creo un array di elementi e valori. Allora faccio (dopo diverse soluzioni possibili, questo è l'unico modo sono in grado di chiamare la funzione JS)

for ($i = 0; $i < sizeof($grade_array); $i++) 
{ 
    $element = $grade_array[$i][2]; 
    echo '<script type="text/javascript">drawChart(true, '.$this->Js->value($grade_array[$i][0]).', '.$this->Js->value($grade_array[$i][1]).','.json_encode($element).');</script>'; 
} 

sembra passare tutti i dati corretti. Dopo aver chiamato la funzione, ho delle linee di debug che stampano i parametri e tutti i parametri sono stampati correttamente. Ho anche notato che se faccio document.write ('test') nello stesso posto del chart.draw(), scriverà 'test' senza alcun errore. Per qualche ragione, se faccio chart.draw(), dice semplicemente che Wkhtmltopdf non ha restituito alcun dato.

+0

Dato il codice che hai postato, non c'è modo per il 'if (typeof doIt === 'boolean')' per restituire true, perché il callback dalla chiamata google.load non ha parametri ('doIt' sarà sempre essere nullo). Devi chiamare la funzione 'drawChart' da qualche altra parte se ricevi un errore sulla riga' var data = new google.visualization.DataTable(); '. È tutto il tuo codice o c'è dell'altro? – asgallant

+0

Mi dispiace per quello. Chiamo la funzione stessa in un secondo momento, dove passo i parametri necessari. So che si sta rompendo su quella linea perché in realtà ho una linea di debug per stampare un messaggio dopo ogni riga, quindi so dove si interrompe; Ho appena rimosso quelli per rendere il codice più facile da leggere per qualcuno. Sono certo che la funzione viene chiamata con i parametri corretti. –

+0

È possibile che si verifichino degli errori se la funzione viene chiamata prima che l'API abbia completato il caricamento: lo scopo del callback è assicurarsi che tutto venga caricato per primo. Prova a organizzare il codice in modo che il trigger per la chiamata 'drawChart' avvenga all'interno del callback dal caricatore google (che non deve necessariamente essere la funzione' drawChart' stessa). – asgallant

risposta

2

Ho risolto questo problema oggi stesso, quindi ecco cosa ha funzionato per me. Per una spiegazione più dettagliata, siete invitati a leggere il mio blog post sull'argomento.

ho avuto solo per fare due semplici modifiche per farlo funzionare:

  1. Fornire l'argomento javascript-delay, per esempio javascript-delay 1000.Questo ritarda l'esecuzione di codice JavaScript per 1000 millisecondi
  2. Aggiungi una richiamata durante il caricamento del API di visualizzazione di Google

function init() { 
 
    google.load("visualization", "1.1", { 
 
    packages: ["corechart"], 
 
    callback: 'drawCharts' 
 
    }); 
 
}

allora si può semplicemente implementare la funzione drawCharts dove è possibile disegnare la grafici esattamente come faresti normalmente.

Assicurati che il tuo markup include quanto segue:

<body onload="init()"> 
    <div id="my-chart"></div> 
</body> 

Basta disegnare il grafico al div con quanto sopra ID, e si dovrebbe essere a posto.

Nota: sto utilizzando l'ultimo binario disponibile (da 0.12.0 a ora). Testato su un'installazione Ubuntu a 64 bit.

+0

Ciao @ Andy0708 - Ho provato questo metodo senza fortuna. Testato usando l'ultima versione di wkhtmltopdf su Ubuntu 14.04.4, Windows 10 e OSX 10.11.6 - Hai qualche esempio di lavoro che posso guardare? – BaronGrivet

2

Invece di utilizzare l'opzione javascript-delay, è meglio attendere il rendering del grafico utilizzando window-status. window-status fa wkhtmltopdf attendere fino a quando lo stato della finestra ha il valore desiderato.

Aggiungi un listener di eventi al grafico

google.visualization.events.addListener(tableChart, 'ready', myReadyHandler); 
function myReadyHandler(){ 
    window.status = "ready"; 
} 

wkhtmltopdf Run utilizzando --window-status ready

6

Problema: Quando si utilizza wkhtmltopdf/wkhtmltoimage il pdf/immagine in una pagina html (con Google Chart), non conteneva il grafico di Google. L'output (pdf/png) era semplicemente vuoto nella posizione in cui appariva il Google Chart. La pagina html originale andava bene, ovviamente.

Soluzione: Ho risolto questo problema (Google Charts + wkhtmltopdf) sostituendo:

<script src="http://www.gstatic.com/charts/loader.js"></script> 

da

<script src="http://www.google.com/jsapi"></script> 

In qualche modo la libreria wkhtmltopdf non poteva gestire una pagina html Grafico Google, che contiene il primo include di javascript.

+1

Tuttavia, in questo modo si sta perdendo qualsiasi nuova funzionalità dall'API Google Charts ... – Adambean

+0

Ha funzionato anche per me. – jbmyid

+0

@Adambean allora qual è la soluzione? – jbmyid