In questa serie in due parti, combineremo l'elemento canvas versatile con la robusta libreria jQuery per creare un plug-in per grafici a barre. In questa prima parte, codificheremo la logica di base del plug-in come versione autonoma.
Oggi creeremo un plug-in per grafici a barre. Non un normale plugin, bada bene. Mostreremo un po 'di amore jQuery per l'elemento canvas per creare un plugin molto robusto.
In questo articolo in due parti, partiremo dall'inizio implementando la logica del plug-in come script autonomo, rifattiandolo in un plug-in e infine aggiungendo tutto il contenuto aggiuntivo sul codice del plug-in. In questa prima parte, ci occuperemo esclusivamente dell'attuazione della logica principale.
Hai bisogno di un esempio prima di iniziare? Ecco qui!
Soddisfatto? Interessato ancora? Iniziamo.
Il nostro plugin ha bisogno di realizzare alcune cose basilari pur non facendo alcune altre cose. Lasciatemi chiarire:
Mentre stiamo esplorando il mondo della tecnologia all'avanguardia, non ancora completamente specificata, abbiamo alcune dipendenze. Perché l'elemento canvas funzioni, la maggior parte dei browser moderni è sufficiente. Ma poiché utilizziamo la nuova API di rendering del testo, abbiamo bisogno di build più recenti. I browser che utilizzano il motore Webkit r433xx e versioni successive o il motore Gecko 1.9.1 e versioni successive devono essere piattaforme eccellenti per il plug-in. Ti consiglio di prendere una build notturna di Chromium o Firefox.
Mi piacerebbe ricordare che il nostro plugin è puramente a scopo di apprendimento. Questo plugin non è in alcun modo destinato a sostituire altri plugin grafici completi come Flot, Plotr e simili. Anche il codice sarà il più dettagliato possibile. Potresti scrivere lontano, lontano codice più efficiente ma per motivi di apprendimento, tutto sarà il più semplice possibile. Sentitevi liberi di refactoring in favore di efficienza nel codice di produzione.
OMG WTF HAX
Anno | I saldi |
---|---|
2009 | 130 |
2008 | 200 |
2007 | 145 |
2006 | 140 |
2005 | 210 |
2004 | 250 |
2003 | 170 |
2002 | 215 |
2001 | 115 |
2000 | 135 |
1999 | 110 |
1998 | 180 |
1997 | 105 |
Niente di speciale sul markup. Farò comunque una rapida panoramica.
Prima di avviare Javascript, permettimi di spiegare il sistema di coordinate del canvas. L'angolo in alto a sinistra funge da origine i.e. (0, 0). I punti vengono quindi misurati rispetto all'origine con x crescente lungo la destra e y crescente lungo la sinistra. Per i matematici inclini, stiamo effettivamente lavorando nel 4 ° quadrante eccetto che prendiamo il valore assoluto di y invece del suo valore negativo. Se hai lavorato con la grafica in altre lingue, dovresti essere a casa qui.
La routine di rendering del rettangolo di Canvas verrà utilizzata estesamente attraverso l'articolo per rendere le barre, la griglia e alcuni altri elementi. Con questo in mente, diamo un'occhiata a quelle routine.
Delle tre routine disponibili, useremo il fillRect e strokeRect metodi. Il fillRect il metodo riempie effettivamente il rettangolo renderizzato mentre il strokeRect il metodo accarezza solo i rettangoli. Oltre a questo, entrambi i metodi hanno gli stessi parametri.
Come sempre, consiglio vivamente di scaricare il codice sorgente e averlo sul lato per riferimento. È più semplice guardare l'immagine grande e analizzare ciascuna funzione una per una, piuttosto che osservare singolarmente ciascuna funzione e quindi creare l'immagine generale nella tua mente.
var barSpacing = 20, barWidth = 20, cvHeight = 220, numYlabels = 8, xOffset = 20, gWidth = 550, gHeight = 200; var maxVal, gValues = [], xLabels = [], yLabels = []; var cv, ctx;
Queste variabili contengono valori codificati per aiutarci nel posizionamento e nel layout del grafico e delle singole barre.
Con il potente motore di selezione di jQuery diventa molto facile per noi ottenere i dati di cui abbiamo bisogno. Qui abbiamo un certo numero di modi per accedere agli elementi necessari. Lasciatemi spiegare alcuni di seguito:
$ ("tr"). children ("td: odd"). each (function () // code here);
Il modo più semplice per accedere alle righe necessarie. Cerca a TR elemento e poi accede a vicenda TD elemento. Fallisce miseramente quando hai più di una tabella sulla tua pagina.
$ ("# dati"). find ("td: odd"). each (function () // code here);
Un modo molto più diretto. Passiamo nell'ID del tavolo e poi accediamo a tutte le altre righe.
$ ("# data tr td: odd"). each (function () // code here);
Come sopra, eccetto che usiamo solo la sintassi del selettore di stile CSS.
$ ("# data trtd: nth-child (2)"). each (function () // code here);
La versione che useremo oggi. In questo modo è molto meglio se abbiamo bisogno di prendere i dati da una riga diversa o, se necessario, più righe.
La versione finale sembra così:
function grabValues () // Accede alla cella della tabella richiesta, estrae e aggiunge il suo valore alla matrice dei valori. $ ("# data tr td: nth-child (2)"). each (function () gValues.push ($ (this) .text ());); // Accede alla cella della tabella richiesta, estrae e aggiunge il suo valore alla matrice xLabels. $ ("# data trtd: nth-child (1)"). each (function () xLabels.push ($ (this) .text ()););
Niente di complicato qui. Usiamo il frammento di codice di cui sopra per aggiungere il valore della cella di tabella al gValues array. Successivamente, facciamo lo stesso eccetto che accediamo alla prima cella della tabella per estrarre l'etichetta richiesta per l'asse x. Abbiamo incapsulato la logica di estrazione dei dati nella sua funzione per la riusabilità e la leggibilità del codice.
function initCanvas () // Prova ad accedere all'elemento canvas e genera un errore se non è disponibile cv = $ ("# graph"). get (0); se (! cv) return; // Cerca di ottenere un contesto 2D per il canvas e genera un errore se non riesci a ctx = cv.getContext ('2d'); if (! ctx) return;
Inizializzazione della tela di routine. Per prima cosa proviamo ad accedere all'elemento canvas stesso. Si genera un errore se impossibile. Quindi, proviamo ad ottenere un riferimento al contesto di rendering 2d attraverso il getContext metodo e genera un errore se non siamo in grado di farlo.
Prima di entrare nel rendering effettivo del grafico stesso, dobbiamo esaminare un certo numero di funzioni di utilità che ci aiutano enormemente nel processo. Ognuno di essi è piccolo da solo, ma sarà ampiamente utilizzato nel nostro codice.
function maxValues (arr) maxVal = 0; per (i = 0; iUna piccola funzione che itera attraverso l'array passato e aggiorna il MAXVAL variabile. Si noti che si gonfia il valore massimo del 10% per scopi speciali. Se il valore massimo viene lasciato così com'è, la barra che rappresenta il valore più alto toccherà il bordo dell'elemento canvas che non vogliamo. Con questo in mente, viene emesso un incremento del 10%.
Normalizzare il valore
function scale (param) return Math.round ((param / maxVal) * gHeight);Una piccola funzione per normalizzare il valore estratto rispetto all'altezza dell'elemento canvas. Questa funzione è usata estensivamente in altre funzioni e direttamente nel nostro codice per esprimere il valore in funzione dell'altezza della tela. Prende un singolo parametro.
Restituzione della coordinata X.
function x (param) return (param * barWidth) + ((param + 1) * barSpacing) + xOffset;Restituisce l'ordinata x al fillRect per aiutarci nel posizionamento di ogni singola barra. Lo spiegherò un po 'più in dettaglio quando verrà usato.
Restituzione della coordinata Y.
funzione y (param) return gHeight - scale (param);Restituisce l'ordinata y al fillRect metodo per aiutarci nel posizionamento di ogni singola barra. Altre spiegazioni un po 'più tardi.
Tornando alla larghezza
function width () return barWidth;Restituisce la larghezza di ogni singola barra.
Restituendo l'altezza
altezza della funzione (param) return scale (param);Restituisce l'altezza della barra da disegnare. Usa il scala funzione per normalizzare il valore e quindi restituirlo al chiamante.
Disegnare le etichette dell'asse X.
function drawXlabels () ctx.save (); ctx.font = "10px 'arial'"; ctx.fillStyle = "# 000"; per (indice = 0; indiceUna semplice funzione per rendere le etichette dell'asse x. Per prima cosa salviamo lo stato attuale della tela, incluse tutte le impostazioni di rendering, in modo che tutto ciò che facciamo all'interno delle funzioni non si estenda mai. Quindi impostiamo la dimensione e il carattere delle etichette. Quindi, iteriamo attraverso il xLabels array e chiama il fillText metodo ogni volta per rendere l'etichetta. Noi usiamo il X funzione per aiutarci nel posizionamento delle etichette.
Disegnare le etichette dell'asse Y.
function drawYlabels () ctx.save (); per (indice = 0; indiceUna funzione un po 'più prolissa. Per prima cosa salviamo lo stato attuale della tela e poi procediamo. Quindi dividiamo MAXVAL di valore in n elementi in cui la variabile numYlabels detta il n. Questi valori vengono quindi aggiunti al yLabels array. Ora, come mostrato sopra, il fillText il metodo è chiamato per disegnare le singole etichette con il y funzione che ci aiuta nel posizionamento di ogni singola etichetta.
Rendiamo uno zero nella parte inferiore della tela per completare il disegno delle etichette Y..
Disegnare il grafico
function drawGraph () for (index = 0; indexLa funzione che disegna le barre effettive nel grafico a barre. Attraversa il gValues matrice e rende ogni singola barra. Noi usiamo il fillRect metodo per disegnare le barre. Come spiegato sopra, il metodo prende quattro parametri, ognuno dei quali è curato dalle nostre funzioni di utilità. L'indice corrente del ciclo viene passato alle nostre funzioni come parametri insieme al valore effettivo contenuto nell'array, secondo necessità.
Il X la funzione restituisce la coordinata x della barra. Ogni volta, viene incrementato del valore della somma di barWidth e barSpacing variabili.
Il y la funzione calcola la differenza tra l'altezza dell'elemento canvas e i dati normalizzati e la restituisce. So che questo suona un po 'sdolcinato, ma questo è dovuto al fatto che i valori di y sulla griglia di tela aumentano quando ci si sposta verso il basso mentre nel nostro grafico i valori y aumentano al salire. Quindi, dobbiamo fare un piccolo lavoro per farlo funzionare nel modo che desideriamo.
Il larghezza la funzione restituisce la larghezza delle singole barre stesse.
Il altezza la funzione restituisce semplicemente il valore normalizzato che verrà utilizzato come altezza della barra da disegnare.
Sommario
In questa prima parte, abbiamo implementato la logica di base del nostro plug-in come versione standalone con l'aspetto e le funzionalità di bare bones. Abbiamo esaminato il sistema di coordinate del canvas, i metodi di rendering del rettangolo, un'elegante estrazione di dati usando l'innata meraviglia di jQuery [ho menzionato quanto mi piace jQuery?], Ho osservato come vengono disegnate le etichette e infine ho esaminato la logica dietro il rendering di il grafico stesso.
Alla fine di questo articolo, l'output dovrebbe apparire così.
Prossimo!
La nostra attuale implementazione è piuttosto carente. Sembra blando, non può creare più grafici sulla stessa pagina, e diciamocelo, è piuttosto spartano sul fronte delle funzionalità. Affronteremo tutto questo la prossima settimana. Nel prossimo articolo faremo:
- Refactor il nostro codice per renderlo un plugin jQuery completo.
- Aggiungi un po 'di piacere per gli occhi.
- Include alcune piccole caratteristiche.
Domande? Critiche? Lodi? Sentiti libero di scrivere i commenti. Grazie per la lettura e, quando sei pronto, passa alla seconda parte!
- Seguici su Twitter o iscriviti al feed RSS di NETTUTS per ulteriori tuts e articoli di sviluppo web giornalieri.