Chart.js, creare grafici interattivi

Introdurre grafici di impatto o diagrammi all’interno di siti o applicazioni mobile è cruciale. Il meccanismo più tipico è quello in cui si interroga il server tramite chiamata AJAX (una API REST o un servizio cloud) e si ricevono i dati in formato JSON (o XML), infine si procede al rendering del grafico direttamente sul client.

Chart.js

Chart.js è una libreria JavaScript che supporta la generazione di ben 6 tipi di grafici differenti, dall’impatto estremamente accattivante.

Il disegno del grafico si avvale del Canvas di HTML5, supportato dalla maggior parte dei browser moderni (e anche su quelli più datati con appositi polyfill) e risponde anche alle interazioni dell’utente, adattandosi in modo “responsive” al device su cui viene prodotto.

Tutte queste funzionalità sono racchiuse in uno script di piccole dimensioni (11 Kb circa), che possono essere ridotte ulteriormente se si usano solo alcuni dei tipi di grafici a disposizione.

Addentriamoci nei dettagli della libreria e vediamo con quale semplicità possiamo utilizzarla per creare grafici nella nostra applicazione Web.

Scaricare la libreria

La libreria può essere scaricata dal repository ufficiale su GitHub, attraverso il client Git preferito o direttamente dalla pagina in formato ZIP. Possiamo scaricare liberamente tutti i file sorgenti del progetto, utili a chi vuole contribuire o approfondire il funzionamento della libreria, oppure limitarci al solo file “Chart.js” (e la sua versione minified “Chart.js.min” per l’uso in produzione) se vogliamo avere accesso a tutti i grafici supportati, oppure ancora prelevare dalla cartella “Src” solo il cuore della libreria (Chart.Core.js) e i file relativi ai singoli grafici che vogliamo utilizzare.

Importare e utilizzare la libreria

Utilizzare la libreria è molto semplice: è sufficiente includere il riferimento allo script nel tag<head> della pagina HTML che ne fa uso, o nel modello (template) che da origine a tutte le pagine (se adottate un framework che fornisce questa possibilità):

<script src="Chart.js"></script>

Se non usate tutti i grafici, potete includere lo script del “core” e quelli dei grafici che vi interessano.

La libreria supporta anche il caricamento tramite “loader JavaScript” come Require.js: per esigenze di brevità, ne omettiamo la trattazione rimandando alla documentazione ufficialedella libreria per il suo utilizzo.

Una volta inclusi gli script, l’ambiente JavaScript sarà arricchito da una variabile globale ‘Chart’, che consente di generare i grafici e di configurare le opzioni della libreria.

Preparazione del Canvas

Il primo passo per creare un grafico è quello di inserire il <canvas> HTML5 all’interno della pagina: la libreria ne assumerà il controllo e sfrutterà le sue potenzialità multimediali per le operazioni di disegno e l’animazione interattiva del grafico tracciato.

Ecco un markup di esempio per la pagina HTML

<canvas id="myChart" width="400" height="400"></canvas>

Assegnamo un id al Canvas (“myChart”, nel nostro esempio) per referenziarlo con semplicità all’interno del codice:

var ctx = document.getElementById("myChart").getContext("2d");

oppure con JQuery:

var ctx = $("#myChart").get(0).getContext("2d");

Per creare il grafico e associarlo al contesto, è sufficiente ricorrere alla funzione costruttoreChart() passando il Canvas come parametro

var myNewChart = new Chart(ctx);

Ora abbiamo a disposizione un oggetto Chart che possiamo utilizzare per disegnare nel Canvas associato tutti i grafici che vogliamo.

Tipi di grafici

L’oggetto Chart fornisce una serie di metodi per creare tutti i grafici supportati dalla libreria; ecco un esempio di chiamata per creare un grafico a barre:

var myNewChart = new Chart(ctx);
// ...
myNewChart.Bar(data, options);

Ecco l’elenco dei tipi di grafici supportati e dei relativi metodi da richiamare:

Tipo di grafico Descrizione Esempio
.Line() Crea un grafico a linee
.Bar() Crea un grafico a barre
.Radar() Crea un grafico a radar
.PolarArea() Crea un grafico polare
.Pie() Crea un grafico a torta
.Doughnut() Crea un grafico a ciambella

Come visto nell’esempio, la chiamata al metodo di creazione del grafico accetta generalmente due parametri:

Parametro Descrizione
data È l’oggetto che contiene i dati da rappresentare all’interno del grafico, ovvero le “serie”; la sua struttura varia in base al tipo specifico di grafico e può contenere anche informazioni su colori, etichette e altri “metadati” che meglio descrivono ciascuna serie da rappresentare.
options Contiene un oggetto con i valori delle opzioni supportate del grafico che determinano le sue caratteristiche, come l’aspetto, il comportamento, gli elementi visibili (e non) al suo interno, le interazioni possibili con l’utente.

Le opzioni supportate da ciascun grafico hanno un valore predefinito che viene utilizzato se l’oggetto passato al parametro options non contiene una proprietà che lo altera.

Creare un grafico

Per addentrarci nei dettagli della libreria, rappresenteremo il grafico più semplice: il grafico a linee, che viene impiegato di solito per la visualizzazione di trend o per confrontare due o più andamenti tra loro sovrapponendoli nel diagramma.

Per poterlo disegnare, dobbiamo creare la struttura dati in JavaScript che contiene i valori da rappresentare e da passare come parametro data al metodo Line(). Oltre ai dati, aggiungiamo anche proprietà che descrivono le caratteristiche da associare a ciascuna serie per poterle differenziare visivamente.

Ecco lo script di esempio completo:

<body>
<canvas id="myLineChart" width="600" height="600"></canvas>
<script>
// Definisco i dati da mostrare nel grafico
var data = {
    labels: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto"],
    datasets: [
        {
            label: "Temperature 2013",
            fillColor: "rgba(99,240,220,0.2)",
            strokeColor: "rgba(99,240,220,1)",
            pointColor: "rgba(99,240,220,1)",
            pointStrokeColor: "#fff",
            pointHighlightFill: "#fff",
            pointHighlightStroke: "rgba(220,220,220,1)",
            data: [8, 11, 18, 22, 24, 26, 34, 39]
        },
        {
            label: "Temperature 2014",
            fillColor: "rgba(205,99,151,0.2)",
            strokeColor: "rgba(205,99,151,1)",
            pointColor: "rgba(205,99,151,1)",
            pointStrokeColor: "#fff",
            pointHighlightFill: "#fff",
            pointHighlightStroke: "rgba(151,187,205,1)",
            data: [16, 18, 22, 24, 26, 28, 32, 36]
        }
    ]
};
// Ottengo il contesto 2D del Canvas in cui mostrare il grafico
var ctx = document.getElementById("myLineChart").getContext("2d");
// Crea il grafico e visualizza i dati
var myLineChart = new Chart(ctx).Line(data);
</script>
</body>

Nello script, la variabile data conterrà un oggetto con le informazioni da mostrare nel grafico; ad esempio, l’oggetto possiede una proprietà labels con le etichette dei valori per l’asse X e una proprietà datasets con le caratteristiche delle serie di dati (etichette, colori del tratto e del riempimento, etc.) e gli effettivi valori da rappresentare sull’asse Y, memorizzati nella proprietàdata di ciascuna serie; la proprietà datasets è un array in quanto possiamo mostrare contemporaneamente più serie di valori nello stesso grafico, attribuendovi caratteristiche diverse per poterli distinguere a colpo d’occhio.

Nell’esempio sopra abbiamo rappresentato le temperature dei primi mesi degli anni 2013 e 2014 (i valori sono del tutto arbitrari e non significativi).

Nell’immagine che segue vediamo come Chart.js disegna il grafico nella pagina:

Osservando l’aspetto del grafico possiamo notare alcune particolarità interessanti:

  • anzitutto Chart.js fissa automaticamente il massimo della scala sull’asse Y basandosi sui valori specificati per le serie, rendendo il grafico estremamente leggibile.
  • Il supporto alla trasparenza nei colori permette di sovrapporre e confrontare tra loro le serie.
  • Spostando il puntatore del mouse sul reticolo che si trova sullo sfondo, vengono mostrate le etichette e i valori delle curve per ciascun “incrocio”.

In breve, possiamo considerare Chart.js una libreria a “configurazione zero”: le impostazioni di default consentono di ottenere una rappresentazione che probabilmente si avvicina molto a quella desiderata, tuttavia è possibile personalizzare nei minimi dettagli il risultato aggiungendo al metodo il secondo parametro options.

Nello script riportato di seguito vediamo le opzioni supportate dal grafico a linee e la spiegazione nei commenti del loro significato.

var options = {
    // {boolean} Indica se visualizzare le linee della griglia
    scaleShowGridLines : true,
    
    // {string} Colore delle linee della griglia
    scaleGridLineColor : "rgba(0,0,0,.05)",
    
    // {number} Spessore delle linee della griglia
    scaleGridLineWidth : 1,
    
    // {boolean} Indica se le linee tra i punti sono curve (di Bezier)
    bezierCurve : true,
    
    // {number} Indica la tensione delle curve tra i punti
    bezierCurveTension : 0.4,
    
    // {boolean} Indica se mostrare un pallino per ogni punto
    pointDot : true,
    
    // {number} Definisce l’arrotondamento di ciascun punto
    pointDotRadius : 4,
    
    // {number} Definisce lo spessore di ciascun punto
    pointDotStrokeWidth : 1,
    
    // {number} Aumenta lo spazio sensibile al click attorno a ciascun punto
    pointHitDetectionRadius : 20,
    
    // {boolean} Indica se visualizzare il tratto per i dataset
    datasetStroke : true,
    
    // {number} Indica lo spessore del tratto per i dataset
    datasetStrokeWidth : 2,
    
    // {boolean} Indica se ciascun dataset deve essere riempito con un colore
    datasetFill : true,
    
    // {string} Definisce il template per il markup della legenda del grafico
    legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.len>h; i++){%><li><span style=\"background-color:<%=datasets[i].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
};
// Crea il grafico e visualizza i dati
var myLineChart = new Chart(ctx).Line(data, options);

Se avete l’esigenza di generare più grafici dello stesso tipo e non volete specificare ogni volta e per ciascuno di essi valori personalizzati per le opzioni, ad esempio per definire uno stile grafico che sia in linea con quello della vostra applicazione, Chart.js offre una scorciatoia per impostare tali valori a livello globale; ad esempio, per disabilitare le curve di Bezier per tutti i grafici Line, è sufficiente scrivere questo:

Chart.defaults.Line.bezierCurve = false;

Gestione degli eventi

Chart.js supporta diversi livelli di interazione con l’utente: oltre a visualizzare automaticamente i valori presenti in un determinato punto del grafico o per una determinata barra colorata a seconda del tipo di diagramma (se l’opzione corrispondente è abilitata), la libreria fornisce anche metodi in grado di restituire ulteriori informazioni sul grafico passando come parametro l’oggetto event ottenuto dalle funzioni di callback.

Questo esempio di codice definisce un callback per l’evento onclick sul controllo Canvas: l’oggetto fornito dalla funzione viene passato al metodo getPointsAtEvent() per ottenere i punti del grafico che si trovano alle coordinate in cui l’utente ha fatto click.

ctx.onclick = function (e)
{
    // Ottiene i punti del grafico che si trovano alle coordinate
    // del click, fornite dall'oggetto che contiene le informazioni
    // relative all'evento intercettato
    var points = myLineChart.getPointsAtEvent(e);
};

Ciascuna tipologia di grafico offre metodi differenti in base al diagramma rappresentato: ad esempio, per i grafici a barre (Bar), il metodo da chiamare è getBarsAtEvent().

Le informazioni ricevute tramite questi metodi possono essere usate per fornire un feedback personalizzato all’utente finale, inviarli tramite una chiamata AJAX e così via.

Creare grafici dinamici

Non è obbligatorio specificare dall’inizio tutti i dati che devono essere rappresentati per poter generare un grafico: il prototipo dell’oggetto che rappresenta un determinato diagramma fornisce i metodi addData() e removeData() con cui è possibile rispettivamente aggiungere e rimuovere dati; il grafico verrà aggiornato dinamicamente in tempo reale.

È possibile chiamare il metodo update() per forzare l’aggiornamento della rappresentazione a video, riproducendo nuovamente le animazioni supportate dalla libreria nella fase iniziale di disegno che rendono il grafico intuitivo e accattivante.

Link utili

Per chi ne sentisse l’esigenza (o come fallback) si può far ricorso a soluzioni lato server per i grafici:

Share this post