Sarà sicuramente capitato a molti di avere la necessità di visualizzare dei dati statistici per la creazione di grafici di ogni genere e sicuramente vi sarete imbattuti in problemi più o meno seri.
PHP non ha direttamente un supporto per questa tipologie di cose, tuttavia usando delle apposite estensioni è possibile realizzare grafici, anche complessi senza grossi problemi.
L'estensione più usata per questo genere di operazioni è sicuramente la GD2, dato che permette un'avanzata elaborazione delle immagini con estrema semplicità. Su questa libreria si basano moduli e classi per php che si occupano della generazione dei grafici semplificando il lavoro, ma vi sono anche altre estensioni che permettono l'elaborazione grafica e tra queste troviamo la MING.
L'estensione Ming di php permette la generazione in tempo reale di SWF, ovvero filmati flash, che possono essere inviati direttamente al browser oppure salvati su disco, dando quindi la possibilità al programmatore di creare una cache invece di creare al volo ogni volta il filmato flash in tempo reale.
Quest'estensione, ovviamente, può anche essere usata per creare ogni genere di filmati con flash utilizzando anche actionscript.
Come Installare l'estensione Ming
L'estensione Ming è già compresa nel pacchetto php (la versione per Windows compressa in formato .zip) quindi il file, php_ming.dll, dovrebbe essere già presente all'interno della cartella delle estensioni di php. Se avete correttamente configurato il php.ini per il caricamento delle estensioni vi basterà trovare la riga ;extension=php_ming.dll e togliere il punto e virgola iniziale.
Fatto ciò riavviate Apache e l'estensione Ming sarà attiva e funzionante sulla vostra installazione di php. Per accertarsi che le librerie Ming funzionino correttamente, è sufficiente eseguire il comando <? phpinfo(); ?> di php e verificare che l'estensione sia caricata correttamente.
È possibile installare l'estensione anche su linux, ma, a tal fine, è necessario installare l'apposito pacchetto o compilare dai sorgenti l'estensione. Una volta eseguita l'installazione vi basterà configurare il php.ini come spiegato in precedenza e riavviare Apache, e l'estensione Ming funzionerà perfettamente.
È consigliabile abilitare anche l'estensione gd2 perché, usata insieme all'estensione Ming, permette operazioni parecchio avanzate e complesse.
Per maggiori informazioni sull'installazione o per scaricare i sorgenti da installare potete andare sul sito ufficiale delle Ming(http://ming.sourceforge.net/) oppure sulla pagina del manuale php che le tratta (http://it.php.net/ming). Se doveste avere problemi per la compilazione, vi consiglio di guardare il wiki che mette a disposizione il sito ufficiale delle Ming o di leggere i commenti presenti nelle pagine del manuale di php, aiutano molto.
Vi consiglio anche di creare una cartella chiamata Ming all'interno della Document Root del vostro web server nella quale mettere tutti i file che a mano a mano vi proporrò, in modo da avere un archivio completo di esempi sempre disponibile.
È inoltre necessario scaricare, sempre dal sito ufficiale, l'archivio dei font dal quale dovete copiare il contenuto della cartella fdb all'interno della cartella ming o all'interno della cartella nella quale metterete i file php contenenti il codice d'esempio.
Nota: Essendo l'estensione ancora in fase di sviluppo molti esempi presenti sul web o, anche, sul manuale di php, potrebbero non funzionare correttamente. In questo caso è necessario installare l'ultima versione di php in modo da avere anche l'ultima versione delle Ming disponibile. Se non vi è possibile installare l'ultima versione di php potete provare a scaricare php_ming.dll da http://kromann.info/php4.php.
Primi Passi
L'estensione Ming vi permette di realizzare quasi tutto quello che vi permette di fare Macromedia Flash MX, in pratica supporta le feature di flash fino alla versione 6, comprensivo di Actionscript.
Quelli che vi mostrerò qui sono soltanto pochi esempi che dovrebbero comunque dare una visione generale delle possibilità offerte dall'estensione.
Per prima cosa creiamo un file chiamato step1.php nel quale inseriremo un codice basilare per creare un file SWF che stamperà a video, all'interno del riquadro del filmato flash, il testo ?Hello World!".
<?php
// Imposto la scala e la versione di flash usata
ming_setScale(20);
ming_useswfversion(6);
// Creo una nuova animazione
$movie = new SWFMovie();
// Imposto la dimensione e lo sfondo
$movie->setDimension(200, 200);
$movie->setBackground(100, 150, 200);
// Imposto il font, l'altezza ed il colore del testo
$font = new SWFFont('fdb/Bitstream Vera Sans.fdb');
$text = new SWFText();
$text->setFont($font);
$text->setHeight(14);
$text->setColor(0, 0, 0);
// Posiziono ed inserisco il testo
$text->moveTo((200/2) - ($text->getWidth('Hello World!') / 2), 200/2);
$text->addString('Hello World!');
// Aggiungo il testo al filmato
$movie->add($text);
// Salvo il file su disco
$movie->save('step1.swf');
?>
<html>
<head>
<title>PHP e Ming: Introduzione - Step 1</title>
</head>
<body>
<object type="application/x-shockwave-flash" data="step1.swf" width="200px" height="200px">
<param name="movie" value="step1.swf" />
</object>
</body>
</html>
Il codice all'inizio imposta alcuni parametri delle Ming, come la scala da utilizzare per i parametri che definiscono le dimensioni e le posizioni, L'estensione Ming gestisce questa tipologia di misure usando i Twips per essere maggiormente precisi, ma, siccome rischia di far confondere, conviene impostare la scala a 20 (un pixel corrisponde a 20 twips, i valori numerici che verranno passati alle Ming saranno in pratica pixel e non twips). A questo punto viene impostata sul valore 6 (ovvero Flash MX), la versione da usare come formato SWF, e viene creata l'animazione impostando la dimensione, 200x200, e lo sfondo.
Il passo successivo è il caricamento di un font e l'aggiunta di un oggetto SWFText, nel quale vengono impostati la dimensione, il font da usare, il colore, la posizione ed il testo da visualizzare. È anche possibile usare il formato RGBA per i colori. Il formato RGBA supporta il canale Alpha, ovvero la trasparenza, e questo ci permette di rendere il testo trasparente. In pratica i metodi che permettono l'inserimento del quarto parametro, A, supportano i colori in formato RGBA.
Una volta creati tutti gli oggetti, è necessario aggiungerli al filmato flash tramite il metodo add dell'oggetto movie.
A questo punto è possibile salvare su disco o inviare direttamente al browser il file Swf. Per comodità d'utilizzo ho preferito salvare sul disco dove risiede il webserver e visualizzare tramite codice html.
Partendo da questo codice è già possibile iniziare a prendere confidenza con queste potenti librerie, ad esempio, richiedendo il nome dell'utente in una pagina e visualizzandolo tramite flash in una seconda pagina, o stampando a video una striscia con le ultime news o gli ultimi post del vostro forum, ed altro ancora.
Sprite o Movie Clip
Chi usa flash sicuramente conosce gli Sprite o i Movie Clip, contenitori per animazioni che permettono, non solo di creare delle animazioni separate dall'ambito globale che svolgono i propri compiti indipendentemente seguendo la timeline globale, ma danno la possibilità che di raggruppare oggetti, facilitando notevolmente il lavoro del programmatore.
Ad esempio è possibile creare del testo che ruota, aumentando la sua velocità di rotazione in maniera incrementale e facendolo fermare una volta compiuto un giro completo di 360°.
Create un file di nome step2.php e inserite all'interno il seguente codice:
<?php
// Imposto la scala e la versione di flash usata
ming_setScale(20);
ming_useswfversion(6);
// Creo una nuova animazione
$movie = new SWFMovie();
// Imposto la dimensione, il colore di sfondo
// e i frame per secondo
$movie->setDimension(200, 200);
$movie->setBackground(100, 150, 200);
$movie->setRate(10);
// Imposto il font, l'altezza ed il colore del testo
$font = new SWFFont('fdb/Bitstream Vera Sans.fdb');
$text = new SWFText();
$text->setFont($font);
$text->setHeight(14);
$text->setColor(0, 0, 0);
$text->addString('Hello World!');
// Creo lo sprite ed aggiungo l'oggetto
$sprite = new SWFSprite();
$tmpOBJ = $sprite->add($text);
$sprite->nextFrame();
// Imposto le varie angolazioni dell'oggetto
// nei vari frame
$tot = 0; $gradi = 0;
while($tot < 360) {
$tmpOBJ->rotate($gradi);
$sprite->nextFrame();
$gradi++;
$tot += $gradi;
}
// Aggiungo lo sprite all'animazione
$tmpOBJ = $movie->add($sprite);
$tmpOBJ->moveTo(100, 100);
// Salvo il file su disco
$movie->save('step2.swf');
?>
<html>
<head>
<title>PHP e Ming: Introduzione - Step 2</title>
</head>
<body>
<object type="application/x-shockwave-flash" data="step2.swf" width="200px" height="200px">
<param name="movie" value="step2.swf" />
</object>
</body>
</html>
Il codice è molto simile al precedente, però ha un'aggiunta che cambia radicalmente tutto il comportamento dell'animazione.
Il ciclo while che si trova nel nuovo codice si occupa di:
- ruotare l'oggetto di un numero di gradi che va aumentando ad ogni ciclo
- di spostarsi avanti nei frame
Una volta raggiunti o superati i 360° il ciclo while si interrompe. Una volta terminato il ciclo while viene aggiunta all'animazione lo sprite e viene posizionato al centro. Fatto questo, lo script procede a salvare e visualizzare l'animazione appena creata.
Come vedete è estremamente semplice creare animazioni usando le ming e con poche righe di codice di possono creare cose ben più complesse. Se volessimo creare uno scroller orizzontale per il testo potremmo fare un qualcosa del genere:
<?php
// Testo da visualizzare e spostamento da eseguire in pixel
$testo = 'Articolo: PHP e Ming: Introduzione';
$moveCol = 10;
// Imposto la scala e la versione di flash usata
ming_setScale(20);
ming_useswfversion(6);
// Creo una nuova animazione
$movie = new SWFMovie();
// Imposto la dimensione, il colore di sfondo
// e i frame per secondo
$movie->setDimension(200, 20);
$movie->setBackground(100, 150, 200);
$movie->setRate(10);
// Imposto il font, l'altezza ed il colore del testo
$font = new SWFFont('fdb/Bitstream Vera Sans.fdb');
$text = new SWFText();
$text->setFont($font);
$text->setHeight(14);
$text->setColor(0, 0, 0);
$text->addString($testo);
// Creo lo sprite ed aggiungo l'oggetto
$sprite = new SWFSprite();
$tmpOBJ = $sprite->add($text);
// Sposto il testo dinamicamente, scorrendolo
// da sinistra a destra
$left_margin = 0 - ($text->getWidth($testo)+1);
$tmpOBJ->moveTo(200, 0);
for ($curr_pos = 200; $curr_pos > $left_margin; $curr_pos -= $moveCol) {
$sprite->nextFrame();
$tmpOBJ->moveTo($curr_pos, 0);
}
// Aggiungo lo sprite all'animazione
$tmpOBJ = $movie->add($sprite);
$tmpOBJ->moveTo(0, 16);
// Salvo il file su disco
$movie->save('step3.swf');
?>
<html>
<head>
<title>PHP e Ming: Introduzione - Step 3</title>
</head>
<body>
<object type="application/x-shockwave-flash" data="step3.swf" width="200px" height="20px">
<param name="movie" value="step3.swf" />
</object>
</body>
</html>
Rispetto a prima il codice è variato veramente poco, infatti al posto del ciclo while che eseguiva la rotazione dello sprite, adesso è presente un ciclo for che si occupa di far scorrere un testo, impostato ad inizio script, e di un numero di pixel, sempre impostato ad inizio script, da destra a sinistra.
Come avete potuto notare, l'estensione è davvero di facile utilizzo, soprattutto per realizzare scroller dinamici o animazioni semplici, e tutto questo senza richiedere una benché minima conoscenza di actionscript e senza dover acquistare costosi ambienti di sviluppo.
Forme
La libreria Ming permette anche di creare degli Shape, ovvero delle forme composte da linee e curve, riempiti o meno.
Tramite questi oggetti è possibile visualizzare a video delle forme con poco codice.
<?php
// Imposto la scala e la versione di flash usata
ming_setScale(20);
ming_useswfversion(6);
// Creo una nuova animazione
$movie = new SWFMovie();
// Imposto la dimensione, il colore di sfondo
// e i frame per secondo
$movie->setDimension(200, 200);
$movie->setBackground(100, 150, 200);
$movie->setRate(10);
// Creo uno Shape (forma)
$shape1 = new SWFShape();
$shape1->setLine(2, 100, 0, 0);
$shape1->setRightFill($shape1->addFill(255, 20, 20, 170));
$shape1->movePenTo(10, 10);
$shape1->drawLineTo(100, 150);
$shape1->drawLineTo(100, 180);
$shape1->drawCurveTo(10, 180, 10, 10);
// Creo uno Shape (forma)
$shape2 = new SWFShape();
$shape2->setLine(2, 100, 0, 0);
$shape2->setRightFill($shape2->addFill(20, 255, 20, 170));
$shape2->movePenTo(100, 10);
$shape2->drawLineTo(160, 10);
$shape2->movePenTo(100, 11);
$shape2->drawCurveTo(0, 300, 160, 11);
// Creo uno Shape (forma)
$shape3 = new SWFShape();
$shape3->setLine(2, 100, 0, 0);
$shape3->setRightFill($shape3->addFill(20, 20, 255, 170));
$shape3->movePenTo(40, 40);
$shape3->drawLineTo(180, 40);
$shape3->movePenTo(40, 41);
$shape3->drawCurveTo(10, 200, 180, 41);
// Aggiungo lo sprite all'animazione
$movie->add($shape1);
$movie->add($shape2);
$movie->add($shape3);
// Salvo il file su disco
$movie->save('step4.swf');
?>
<html>
<head>
<title>PHP e Ming: Introduzione - Step 4</title>
</head>
<body>
<object type="application/x-shockwave-flash" data="step4.swf" width="200px" height="200px">
<param name="movie" value="step4.swf" />
</object>
</body>
</html>
Il codice che ho riportato si occupa di creare 3 forme, di cui due composte da una sola curva ed una sola linea, ed il primo shape, composto da due linee ed una curva, tutte e 3 trasparenti e colorate che si sovrappongono. Come avevo detto in precedenza, è possibile usare il canale ALPHA del colore per utilizzare la trasparenza, infatti è possibile notare come nella zona in cui si incrociano le 3 forme il colore non corrisponda a nessuno dei 3 colori usati ma bensì ad una loro mistura.
Conclusioni
Con quest'ultimo esempio di codice, si conclude l'articolo che vi ha introdotto alle Ming. Un'introduzione semplice ma che vi da la possibilità di iniziare a muovervi all'interno delle possibilità che questa potente estensione vi offre.
Ricordo ancora una volta che sul sito principale è possibile scaricare una grande quantità di documentazione e guide ed è possibile visionare parecchi esempi di codice e leggere svariati consigli utili sul Wiki disponibile sul sito.
Inoltre vi consiglio anche di andare a guardare i vari esempi disponibili sul sito gazb. Come ultimo link riporto il manuale di PHP, disponibile online, nel quale viene trattata l'estesione Ming in ogni sua parte.
Come è stato accennato nella prima parte dell'articolo, l'estensione Ming permette di creare grafici più o meno complessi ed elaborati, in base alle proprie esigenze.
Essendo una libreria molto flessibile e con funzioni molto avanzate, permette di realizzare anche grafici tridimensionali o che trattano dati multipli e così via: dipende tutto dall'immaginazione di chi le usa. L'obiettivo di quest'articolo è, però, introdurre le possibilità offerte da questa estensione per la realizzazione di grafici, quindi verranno trattati i concetti base e non avanzate formule matematiche per la generazione di grafici.
Per chi non lo avesse fatto, consiglio di leggere la prima parte dell'articolo Filmati Flash e PHP con Ming, la parte che introduce all'uso della libreria, in modo da iniziare a prendere confidenza con questo modulo e comprendere meglio ciò che verrà trattato nel corpo dell'articolo.
Cos'è un grafico
Per poter realizzare un grafico bisogna capire com'è fatto e da cosa è composto. Un grafico è un insieme di dati che vengono confrontati in base a dati criteri scelti dall'utente e, infine, visualizzati a video o stampati su carta. Di solito, per la visualizzazione, si utilizzano forme geometriche basilari o avanzate, partendo dalle semplici linee per arrivare a parallelepipedi rettangolari o torte tridimensionali.
Non ha importanza il sistema che viene usato per rappresentare i dati di un grafico, ne hanno invece i parametri di configurazione. Per parametri di configurazione intendo tutta una serie di impostazioni che permettono di confrontare i dati tra loro utilizzando gli stessi criteri.
Se vogliamo confrontare le spese mensili dell'anno 2004 possiamo creare un grafico a barre verticali, nel quale ogni barra indicherà la spesa di un mese. Inoltre è importante stabilire l'intervallo dei valori, ovvero il valore minimo ed il valore massimo, che i dati potranno avere: nel nostro caso possiamo decidere che il valore minimo parta da 500 € e il valore massimo arrivi a 2000 €.
Prepariamoci a realizzare un grafico
Come dice il titolo stesso del paragrafo, adesso ci occuperemo della realizzazione dei grafici tramite PHP e Ming. Il grafico che andremo a realizzare sarà quello descritto nell'esempio precedente.
In allegato all'articolo troverete la classe che ho sviluppato per disegnare grafici a barre verticali tramite l'estensione. Qui nel corpo dell'articolo tratteremo le parti più importanti, quelle che si occupano del settaggio delle impostazioni, della raccolta dei dati ed infine la creazione, visualizzazione/salvataggio dell'SWF. Nell'archivio allegato, oltre al codice della classe, sarà presente anche una raccolta di font, scaricata dal sito ufficiale delle Ming, utilizzati per disegnare il testo nel file flash.
Costruttore della classe
La classe che andremo a costruire raccoglierà, come prima cosa, i parametri base, quelli che ci servono per realizzare il grafico, ed altri parametri vari, come il colore di sfondo, o l'altezza del font e cosi via.
function MGGraph_VBar($width, $height, $minValue, $maxValue, $numGridLines, $fontHeight, $bgColor) {
.
.
.
$this->width = $width;
$this->height = $height;
$this->minValue = $minValue;
$this->maxValue = $maxValue;
$this->numGridLines = $numGridLines;
$this->fontHeight = $fontHeight;
$this->bgColor = $bgColor;
}
Il costruttore accetta come parametri la dimensione dell'SWF,i valori minimi e massimi dei dati che saranno successivamente inseriti, il numero di linee orizzontali da visualizzare nella griglia, l'altezza del testo in pixel, ed infine lo sfondo del filmato, passato come array di 3 elementi contenente il canale rosso, verde e blu.
Acquisizione dei dati
Una volta acquisite le impostazioni del grafico è necessario settare i parametri dei vari dati, quindi con un apposito metodo recuperiamo il valore, la descrizione, il colore della linea ed infine il colore di riempimento.
function addBar($value, $text, $fgColor = array(200, 90, 30), $fillColor = array(20, 180, 50)) {
$this->bars[] = array(
$value,
$text,
$fgColor,
$fillColor
);
}
Com'è possibile vedere, il codice che acquisisce i dati è veramente semplice: non fa altro che leggere i vari parametri in ingresso ed impostarli all'interno di un array bidimensionale.
Il colore di ForeGround, ovvero quello in primo piano, verrà usato al momento della creazione dell'SWF sia per il testo della descrizione, sia per il bordo della barra verticale.
Il quarto parametro, $fillColor, accetta un array sia a 3, sia a 4 elementi. Nel caso venga impostato il quarto elemento nell'array, verrà utilizzato il canale alpha del colore, permettendo quindi la trasparenza. Di default il valore del canale alpha è impostato su 220 per dare un leggero effetto di trasparenza. Il canale alpha, come gli altri canali del colore, va da 0 a 255: i valori che tendono verso lo zero indicano la trasparenza mentre quelli che tendono verso il limite superiore indicano l'opacità.
Creazione del grafico
Il codice che riporterò di seguito, sarà diviso in più parti per poterlo illustrare meglio. Il grafico è suddiviso in vari elementi grafici:
- Ascissa e ordinata
- Linee orizzontali della griglia e relativa descrizione
- Barre verticali e descrizione
Come prima cosa, però, il codice si occupa di creare il filmato SWF ed impostare tutta una serie di oggetti e valori che verranno usati nel corso della creazione dell'animazione stessa.
function &_prepareSwf() {
// Crea il filmato ed imposta alcune propietà basilari
$movie = &new SWFMovie();
$movie->setDimension($this->width, $this->height);
$movie->setBackground($this->bgColor[0], $this->bgColor[1], $this->bgColor[2]);
// Instanzia il font di default
$font = new SWFFont('fdb/Bitstream Vera Sans.fdb');
// Inizializza un oggetto TEXT che verrà usato per
// calcolare le lunghezze del testo
// Instanzio l'oggetto
$text = new SWFText();
// Imposto il font da usare e l'altezza del testo
$text->setFont($font);
$text->setHeight($this->fontHeight);
// Calcola alcune misure
$YValueWidth = $text->getwidth($this->maxValue) + 20;
$maxHeightUsable = $this->height - (10 + 41 + 5);
Com'è possibile notare, il nome della funzione è preceduto da una "&" per far ritornare l'oggetto movie come riferimento, in modo da evitarne una copia. Questo è dovuto al modo di lavorare della classe: la funzione _prepareSwf non viene richiamata direttamente dall'esterno, ma da un metodo della classe. L'underscore iniziale ("_") sta proprio ad indicare che il metodo è privato.
Vengono quindi impostate le dimensioni e lo sfondo del filmato, ed in seguito viene caricato il font che verrà usato per disegnare il testo. Viene anche creato un oggetto SWFText che servirà solo a calcolare la larghezza del testo in pixel, per poter eseguire i posizionamenti correttamente. Subito dopo vengono calcolate la larghezza massima del testo a sinistra della griglia e l'altezza massima utilizzabile dalla griglie e dalle barre (che differisce dall'altezza massima utilzzabile).
A questo punto vengono create ascissa ed ordinata tenendo una distanza di 10 pixel da tutti e quattro i bordi.
// Inizializza lo shape
$grid = &new SWFShape();
$grid->setLine(2, 10, 10, 10);
// Disegna l'asse verticale
$grid->movePenTo($YValueWidth, 10);
$grid->drawLineTo($YValueWidth, $this->height - 10);
// Disegna l'asse orizzontale
$grid->movePenTo(10, $this->height - 40);
$grid->drawLineTo($this->width - 10, $this->height - 40);
// Aggiunge la griglia all'oggetto MOVIE
$movie->add($grid);
Viene impostato lo spessore della linea su 2 pixel per dare maggiore risalto alle due linee. Inoltre la linea orizzontale disterà 40 pixel dal bordo inferiore, per distanziarlo maggiormente.
Proseguendo vengono create le linee orizzontali della griglia e viene aggiunto il testo che indica il valore corrispondente a quella linea:
// Instanzia l'oggetto ed imposta le proprietà
$gridHLines = &new SWFShape();
$gridHLines->setLine(1, 30, 30, 30);
// Esegue alcune misurazioni
$gridVertDistance = ($maxHeightUsable / $this->numGridLines);
$vertInterval = ($this->maxValue - $this->minValue) / $this->numGridLines;
$currValue = $this->minValue;
// Aggiunge il testo del punto zero
$tmpYPos = $this->height - 40 + 1 + $this->fontHeight;
$tmpTEXT = &new SWFText();
$tmpTEXT->setFont($font);
$tmpTEXT->setHeight($this->fontHeight);
$tmpTEXT->setColor(0, 0, 0);
$tmpTEXT->moveTo($YValueWidth - (2 + ($text->getwidth($currValue))), $tmpYPos);
$tmpTEXT->addstring($currValue);
$movie->add($tmpTEXT);
$currValue += $vertInterval;
for ($currLine = 1; $currLine <= $this->numGridLines; $currLine++) {
// Calcola la posizione Verticale della linea
$tmpYPos = $this->height - (41 + ($gridVertDistance * $currLine));
// Aggiunge la linea
$gridHLines->movePenTo($YValueWidth, $tmpYPos);
$gridHLines->drawLineTo($this->width - 10, $tmpYPos);
// Aggiunge il testo
$tmpTEXT = &new SWFText();
$tmpTEXT->setFont($font);
$tmpTEXT->setHeight($this->fontHeight);
$tmpTEXT->setColor(0, 0, 0);
if ($currLine == $this->numGridLines) {
$tmpTEXT->moveTo($YValueWidth - (2 + ($text->getwidth($this->maxValue))), $tmpYPos + (int)($this->fontHeight/2) -1 );
$tmpTEXT->addstring($this->maxValue);
} else {
$tmpTEXT->moveTo($YValueWidth - (2 + ($text->getwidth(ceil($currValue)))), $tmpYPos + (int)($this->fontHeight/2) -1 );
$tmpTEXT->addstring(ceil($currValue));
}
$movie->add($tmpTEXT);
// Incrementa il valore corrente
$currValue += $vertInterval;
}
// Aggiunge la griglia delle linee orizzontali al filmato
$movie->add($gridHLines);
Il codice sopra riportato esegue alcuni calcoli che verranno poi usati all'interno del ciclo per disegnare le varie linee orizzontali posizionandole correttamente.
Prima del ciclo for, viene disegnato il testo del punto zero, ovvero quello del valore minimo. All'interno del ciclo, prima di disegnare il testo, la classe verifica se questo è giunto alla fine, in modo da stampare direttamente il valore massimo, per evitare delle piccole, ma fastidiose, differenze.
Infine vengono aggiunte le barre verticali e la descrizione:
// Imposta alcuni valori iniziali
$dispWidth = $this->width - ($YValueWidth + 2 + 10 + 30);
$widthForBar = $dispWidth / count($this->bars);
$leftPosition = $YValueWidth + 2 + 15;
$baseYPos = $this->height - 40 - 1;
// Cicla l'elenco di barre verticali da visualizzare a video
while(list(, $vBar) = each($this->bars)) {
// Calcola l'altezza della barra
if ($vBar[0] == $this->minValue) {
// Se il valore è uguale al valore minimo
// l'altezza è uguale a zero
$heightBar = 0;
} else {
// Se il valore della barra è maggiore del valore minimo
// Calcola l'altezza in pixel della barra
$heightBar = (($vBar[0] - $this->minValue) / ($this->maxValue - $this->minValue)) * $maxHeightUsable;
}
// Aggiunge la barra verticale
$tmpSHAPE = &new SWFShape();
$tmpSHAPE->setLine(1, $vBar[2][0], $vBar[2][1], $vBar[2][2]);
$tmpSHAPE->setRightFill($tmpSHAPE->addFill($vBar[3][0], $vBar[3][1], $vBar[3][2], isset($vBar[3][3]) ? $vBar[3][3] : 220 ));
$tmpSHAPE->movePenTo($leftPosition + 5, $baseYPos);
$tmpSHAPE->drawLineTo($leftPosition + 5, $baseYPos - $heightBar);
$tmpSHAPE->movePenTo($leftPosition + 5, $baseYPos - $heightBar);
$tmpSHAPE->drawLineTo($leftPosition + $widthForBar - 5, $baseYPos - $heightBar);
$tmpSHAPE->movePenTo($leftPosition + $widthForBar - 5, $baseYPos - $heightBar);
$tmpSHAPE->drawLineTo($leftPosition + $widthForBar - 5, $baseYPos);
// Aggiungo lo shape al filmato
$movie->add($tmpSHAPE);
// Aggiunge il testo
$tmpTEXT = &new SWFText();
$tmpTEXT->setFont($font);
$tmpTEXT->setHeight($this->fontHeight);
$tmpTEXT->setColor($vBar[2][0], $vBar[2][1], $vBar[2][2]);
$tmpTEXT->moveTo(($leftPosition + ($widthForBar / 2)) - ($tmpTEXT->getWidth($vBar[1]) / 2), $this->height - 40 + 1 + $this->fontHeight);
$tmpTEXT->addstring($vBar[1]);
$movie->add($tmpTEXT);
// Sposto il cursore verso destra
$leftPosition += $widthForBar;
}
Viene calcolata, come prima cosa, la larghezza massima usabile, quella disponibile per ogni barra, la posizione verticale dalla quale cominciare a disegnare ed infine la posizione orizzontale dalla quale tutte le barre verticali partiranno, ovvero la coordinata Y iniziale.
Il ciclo while scorre l'array dei dati e calcola l'altezza di ciascuna barra usando una proporzione, verificando, però, che il valore impostato sia diverso da quello minimo. Nel caso in cui il valore del dato ed il valore minimo corrispondano, la classe imposta direttamente l'altezza della barra a zero.
Il codice, di seguito, disegna tre linee, riempe lo shape appena disegnato ed infine aggiunge la descrizione della barra verticale centrandolo.
Salvataggio o visualizzazione del filmato
Come già accennato, il metodo _prepareSwf non viene richiamato direttamente, ma dai metodi pubblici save(), che salva su file, e output() che invia al browser.
function save($filename) {
$movie = &$this->_prepareSwf();
$movie->save($filename);
}
function output($compression = 9) {
$movie = &$this->_prepareSwf();
header('Content-type: application/x-shockwave-flash');
$movie->output($compression);
flush();
}
Nel caso di salvataggio su file è necessario specificare il nome del file sul quale salvare. Per l'invio a browser è possibile impostare il livello di compressione, ma è consigliabile lasciare quello di default, 9, in modo da ottenere la compressione massima.
Eseguiamo la classe
<?php
require_once('mggraph_vbar.class.php');
$VGraph = &new MGGraph_VBar(
600, // Larghezza
300, // Altezza
500, // Valore minimo
2000, // Valore massimo
10, // Numero di linee nella griglia
12, // Dimensione font in pixel
array (
240, // Componente ROSSO del colore di sfondo
240, // Componente VERDE del colore di sfondo
240 // Componente BLU del colore di sfondo
)
);
$VGraph->addBar(708, "Gen");
$VGraph->addBar(1200, "Feb");
$VGraph->addBar(600, "Apr");
$VGraph->addBar(1400, "Mar", array(10, 50, 180), array(200, 10, 10, 80));
$VGraph->addBar(1500, "Mag");
$VGraph->addBar(830, "Giu");
$VGraph->addBar(1700, "Lug");
$VGraph->addBar(1800, "Ago");
$VGraph->addBar(100, "Set", array(80, 150, 180), array(80, 150, 180, 90));
$VGraph->addBar(2000, "Ott");
$VGraph->addBar(1150, "Nov");
$VGraph->addBar(784, "Dic");
$VGraph->save('graph.swf');
?>
Utilizzando questo semplice codice, è possibile stampare a video 12 barre verticali, ognuna indicante un mese dell'anno, le quali riportano a video le spese del mese al quale si riferiscono. Modificando i valori passati al metodo addBar della classe, è possibile modificare il grafico con estrema semplicità.
Conclusioni
Come si vede, usando l'estensione Ming, si possono realizzare strutture per disegnare grafici velocemente. Ad esempio è possibile modificare il codice in allegato per far gestire una coppia di dati, invece di un dato singolo: oltre alle spese mensili anche gli introiti, in modo da poter confrontare le uscite ed entrate di ogni mese. Accoppiando questa libreria con i database è veramente molto facile realizzare software che creino reportage facili da comprendere.
È possibile realizzare grafici a barre orizzontali, a linee o punti, o tridimensionali mantenendo il concetto base sempre uguale, ovvero acquisire dei dati, che, a prescindere dalla forma, permettano di realizzare grafici velocemente.