n° 185
Maggio/Giugno 2013
Maggio 24, 2013, 05:20:29 am *
Benvenuto! Accedi o registrati.
Hai dimenticato l'e-mail di attivazione?

Accesso con nome utente, password e durata della sessione
Notizia:
 
   Indice   Linux Windows Techassistance Gameassistance videogame hardware Aiuto Ricerca Agenda Downloads Accedi Registrati  

* Messaggi recenti
Messaggi recenti
Pagine: [1]   Vai giù
  Stampa  
Autore Discussione: Creare PIE CHART Animato con HTML5  (Letto 1339 volte)
0 utenti e 1 Utente non registrato stanno visualizzando questa discussione.
a.sicuro
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 4


Mostra profilo
« inserita:: Marzo 05, 2013, 10:57:23 am »

Buon giorno, riprendendo l'articolo pubblicato dal Dr. Carlo Daniele sul numero 184 di Io Programmo, ho approfondito un pò lo studio dell'oggetto canvas, per estendere le funzionalità della creazione dei grafici.
Il tip che propongo mira alla creazione di un grafico a torta animato (Pie Chart).

Il concetto alla base è abbastanza semplice, e sfrutta la funzione arc() dell'oggetto canvas.
senza dilungarmi nelle spiegazioni (anche perchè il codice è abbastanza semplice), spendo due parole solo sula funzione arc() dell'oggetto canvas e sulle funzioni che andrò ad implementare per creare il grafico.

la funzione arc() crea un arco di circonferenza, utilizzando i seguenti parametri:
  • centerX coordinata di centro X della circonferenza
  • centerY coordinata di centro Y della circonferenza
  • radius raggio della circonferenza
  • initialAngle porzione di angolo iniziale dal quale tracciare l'arco
  • finalAngle porzione di angolo finale dal quale tracciare l'arco
  • anitClockWise valore booleano che indica se il disegno dell'arco deve seguire un senso antiorario

Bene, a questo punto inseriamo nella pagina html i due oggetti che utilizzeremo

Codice:
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<div id="legendSpace" style="width:400"></div>

e partiamo subito con lo script
definiamo per prima cosa alcune variabili di utilizzo globale

Codice:
<script  type="text/javascript">
    var dataPie = [10.00, 5.00, 40.73, 4.27, 40.00]; //dati percentuali del grafico
    var dataPieColor = ["red", "yellow", "green", "blue", "gray"]; //colori dei settori del grafico
    var dataPieLegend = ["Legenda1", "Legenda2", "Legenda3", "Legenda4", "Legenda5"]; //testo della legenda dei colori
    var dataPieData = ["Dati aggiuntivi 1", "Dati aggiuntivi 2", "Dati aggiuntivi 3", "Dati aggiuntivi 4", "Dati aggiuntivi 5"]; // dati aggiuntivi

    var canvas = document.getElementById("canvas"); // riferimento all'oggetto canvas
    var ctx; //Canvas context
    var lastangle = 0; // porzione di angolo finale dell'ultimo arco disegnato
    var centerX = canvas.width / 2; //centro della circonferenza (X)
    var centerY = canvas.height / 2; //centro della circonferenza (Y)
    var radius = 75; // raggio
    var speed = 10; // Velocità animazione (ms)
    var currentloop = 0; // frame corrente dell'animazione
    var totalloops = 100; // frame totali dell'animazione
    var currentIndex = 0; //indice dei dati visualizzati e disegnati

    var color = dataPieColor[currentIndex]; //colore dell'arco corrente da disegnare
    var countPercentage = dataPie[currentIndex]; // dato percentuale corrente da calcolare

a questo punto implementiamo la prima funzione, quella che richiameremo per avviare l'animazione
Codice:
function dataPieInit() {
    if (dataPie && dataPieColor && dataPieData && dataPieLegend) {
        if (canvas && canvas.getContext) {
            ctx = canvas.getContext("2d");
            if (ctx) {
                ctx.clearRect(0, 0, canvas.width, canvas.height);
            }
        }
        plot();
        createLegend();
    }
}

la funzione dataPieInit() inizializza gli oggetti e richiama la funzione plot() che disegna il gafico e la funzione createLegend() che crea la tabella con i simboli di legenda

ecco la funzione plot()
Codice:
function plot() {
    if (dataPie) {
        if (currentloop < totalloops) { // controllo che il passo corrente sia minore del totale dei frame
            ctx.fillStyle = color; //imposto il colore
            ctx.beginPath();
            ctx.moveTo(centerX, centerY); //mi sposto al centro
            ctx.arc(centerX, centerY, radius, lastangle, lastangle + ((Math.PI * 2 * 1 / totalloops) + 0.02), false); //traccio un arco
            ctx.lineTo(centerX, centerY); //tiro le linee dagli estremi dell'arco al centro (creo in questo modo un settore circolare)
            ctx.fill(); // riempio il settore circolare con il colore corrente
            lastangle += Math.PI * 2 * 1 / totalloops; //aggiorno l'angolo in modo che il successivo arco parta dalla fine del precedente.
            currentloop++; //incremento il passo
            updateData(); // aggiorno i dati
            setTimeout("plot()", 10); // ripeto la funzione plot() dopo 10ms.

        }
        else { // se sono arrivato alla fine dei frame, la circonferenza è stata tracciata, ora è il momento di disegnare i valori percentuali nei posti giusti.
            var initAngle = 0; //imposto l'angolo iniziale
            for (var i = 0; i < dataPie.length; i++) {
                //calcolo l'angolo finale
                var finalAngle = initAngle + Math.PI * 2 * (dataPie[i] / 100); // calcolo l'angolo finale in base al dato percentuale contenuto nel vettore
                var middleAnglePos = finalAngle - ((finalAngle - initAngle) / 2); // posizione mediana dell'angolo
                initAngle = finalAngle;

                var textPercentage = parseFloat(dataPie[i]).toFixed(2).toString() + "%";  //valore percentuale in stringa
                //calcolo la coordinata x del testo, a partire dal centro
                var xpos = (Math.cos(middleAnglePos) * (radius)) + (Math.cos(middleAnglePos) * (4 * textPercentage.length)) + centerX ;
                //e poi la y...
                var ypos = (Math.sin(middleAnglePos) * (radius)) + (Math.sin(middleAnglePos) * (4 * textPercentage.length)) + centerY ;
                ctx.fillStyle = "black"; //testo nero
                ctx.fillText(textPercentage, xpos, ypos); //scrivo il testo
            }

        }
    }

}

la funzione plot(), in pratica controlla se il frame corrente sia minore del numero di frame dell'animazione,  quindi traccia un settore di circonferenza, a partire dall'angolo alla fine dell'ultimo settore di circonferenza creato con un'ampiezza calcolata in base all'incremento dei frame/il numero totale dei frame (in questo caso 1/100).

se il frame corrente arriva al totale, la funzione disegna sul grafico i valori percentuali dei dati.

definiamo la funzione updateData() richiamata all'interno di plot(), che  controlla se aggiornare l'indice dei vettori contenenti i dati del grafico, in base alla percentuale correntemente disegnata.

Codice:
function updateData() {
    if (dataPie && countPercentage) {
        if (currentloop >= Math.round(countPercentage))  // la funzione è calcolata con un arrotondamento.
        {
            currentIndex++;
            if (currentIndex < dataPie.length) {
                countPercentage += dataPie[currentIndex]; //aggiorno il contatore globale della percentuale, in modo che quando il frame corrente SUPERA questo valore, vuol dire che è il momento di aggiornare l'indice dei dati.
                color = dataPieColor[currentIndex];
            }
        }
    }
}

Infine definiamo la funzione createLegend, che crea la tabella con la legenda dei colori del grafico:
Codice:
function createLegend() {
    var columnsXrows = 3; // quante colonne per riga vogliamo
    var currentColumn = 1;
    var legendLayer = document.getElementById("legendSpace");
    var table = document.createElement("table");
    //attributi di stile, si possono manipolare per ottenere stili diversi
    table.setAttribute("border", "0");
    table.setAttribute("cellpadding", "2px");
    table.setAttribute("cellspacing", "0");
    table.setAttribute("style", "width:100%");

    var row = document.createElement("tr");

    legendLayer.appendChild(table);
    for (var i = 0; i < dataPie.length; i++) {
        if ((currentColumn % (columnsXrows + 1)) == 0) {
            currentColumn = 0;
            table.appendChild(row);
            row = document.createElement("tr");
        }
        //creo 2 "td" , uno per il quadrato colorato e l'altro per la descrizione e i dati aggiuntivi (inseriti come tooltip)
        var td = document.createElement("td");

        //create colored square
        td.setAttribute("style", "cursor:pointer;width:20px;height:20px;background-color:" + dataPieColor[i]);
        td.innerHTML = "&nbsp;"
        row.appendChild(td);
        //Create text
        td = document.createElement("td");
        td.innerHTML = dataPieLegend[i];
        td.setAttribute("style", "cursor:pointer;font-size:8pt;font-family:Arial");
        td.setAttribute("title", dataPieData[i]);
        row.appendChild(td);
        currentColumn++;

    }
    table.appendChild(row);
}


questa funzione crea dinamicamente una tabella contenente delle coppie di colonne COLORE/LEGENDA, con un TOOLTIP che è contenuto nel vettore dei dati aggiuntivi dataPieData[]

A questo punto, chiamiamo la funzione dataPieInit() e vediamo il risultato.

Codice:
    dataPieInit();
</script>
</body>

A presto!! Sorriso
Registrato
MatrixTeo
Jr. Member
**

Karma: +1/-0
Scollegato Scollegato

Messaggi: 65



Mostra profilo WWW
« Risposta #1 inserita:: Marzo 06, 2013, 05:44:23 pm »

Ti ringrazio, molto interessante Occhiolino

Sarebbe utile, per chi ha poca dimestichezza, una demo (jsfiddle Occhiolino ) e uno zip col progetto completo, ma per me è già perfetto così Occhiolino
Registrato
a.sicuro
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 4


Mostra profilo
« Risposta #2 inserita:: Marzo 06, 2013, 06:30:38 pm »

Ciao innanzitutto grazie :-)
Comunque per poter far girare il progetto puoi anche soltanto creare una pagina HTML e sostituire al body della tua pagina le porzioni di codice in ordine di inserimento. Già  facendo così anche offline, su un browser di ultima generazione, funziona.

Comunque sia grazie per il consiglio, la prossima volta lo inserirò, non ho molta dimestichezza nemmeno io, questo è il mio primo post in assoluto Sorriso

A presto!
Registrato
Pagine: [1]   Vai su
  Stampa  
 
Vai a:  

Copyright © 2011 Edizioni Master SpA. p.iva : 02105820787

Tutti i diritti di proprietà letteraria e artistica riservati. - Privacy



Links to Page