Condividi tramite


Il presente articolo è stato tradotto automaticamente.

Creazione di applicazioni HTML5

Utilizzo di Canvas HTML5 per la visualizzazione dei dati

Brandon Satrom

Scaricare il codice di esempio

Nei primi giorni on-line, quando il Web era poco più di un insieme di collegamenti e testo statico, c'era il crescente interesse nel sostenere altri tipi di contenuto.Nel 1993, Marc Andreessen, creatore del browser Mosaic, che si sarebbe evoluto in Netscape Navigator, proposto il tag IMG come standard per l'incorporamento di immagini in linea con il testo su una pagina.Poco dopo, il tag IMG divenne lo standard de facto per l'aggiunta di risorse grafiche alle pagine Web — uno standard che è ancora in uso oggi.Si potrebbe anche sostenere che, come ci siamo spostati dal Web di documenti sul Web delle applicazioni, il tag IMG è più importante che mai.

Media, in generale, è certamente più importante che mai, e però la necessità di media sul Web si è evoluto nel corso degli ultimi 18 anni, l'immagine è rimasta statica.Autori Web sempre più hanno cercato di utilizzare supporti dinamici quali animazioni interattive, audio e video nei loro siti e applicazioni e, fino a poco tempo, la soluzione primaria era un plug-in come Flash o Silverlight.

Ora, con HTML5, elementi multimediali nel browser ottenere un bel calcio in pantaloni.Probabilmente avete sentito di nuovo tag Audio e Video, che consente di questi tipi di contenuto di funzionare come cittadini di prima classe nel browser, nessun plug-in necessari.Articolo del mese prossimo riguarderà sia di questi elementi e loro API in profondità.Hai probabilmente sentito anche dell'elemento canvas, una superficie di disegno con un ricco set di API JavaScript che vi darà il potere di creare e manipolare immagini e animazioni al volo.Che cosa ha fatto IMG per contenuti grafici statici, tela ha il potenziale per fare per contenuti dinamici e scriptable.

Come eccitante come l'elemento canvas è, però, si soffre un po ' di un problema di percezione.A causa della sua potenza, tela di solito è dimostrato tramite animazioni complesse o giochi, e mentre queste trasmettere ciò che è possibile, si può anche portare a credere che lavorare con tela è complicato e difficile, qualcosa che dovrebbe essere tentato solo per casi complessi, come animazione o giochi.

Nell'articolo di questo mese, mi piacerebbe fare un passo indietro da sfarzo e complessità di tela e vi mostreremo alcuni usi semplici, base di esso, tutti con l'obiettivo di posizionamento la tela come una potente opzione per la visualizzazione dei dati nelle applicazioni Web.Con questo in mente, mi concentrerò su come può iniziare con la tela e come disegnare testo, forme e linee semplici.Poi parlerò di come è possibile lavorare con gradienti in vostra forme, così come come per aggiungere immagini esterne a una tela.Infine, e come ho fatto per tutta questa serie, sarò wrap up con una breve discussione su supporto tela polyfilling per browser meno recenti.

Introducendo la tela di HTML5

Base alla specifica W3C HTML5 (w3.org/TR/html5/the-canvas-element.html), l'elemento di tela "fornisce script con una tela di bitmap dipendenti dalla risoluzione, che può essere utilizzato per il rendering grafici, grafica del gioco o altre immagini visive al volo." Tela è effettivamente definita attraverso due specifiche W3C.Il primo è come una parte della specifica di nucleo di HTML5, dove l'elemento stesso è definito in dettaglio.Questa specifica copre come utilizzare l'elemento di tela, come per ottenere il suo contesto di disegno, API per l'esportazione di tela considerazioni contenuto e sicurezza per i produttori di browser.Il secondo è il contesto 2D HTML Canvas (w3.org/TR/2dcontext), che arriva a in un attimo.

Guida introduttiva a tela è semplice come l'aggiunta di un <canvas> elemento HTML5 markup, come segue:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>My Canvas Demo </title>               
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <canvas id="chart" width="600" height="450"></canvas>       
  </body>
</html>

Anche se ora ho una tela eleme­­nt nel DOM, ponendo questo markup della pagina non fa nulla, come l'elemento canvas è privo di contenuto, fino a quando non si aggiunge. Ecco che entra contesto del disegno. Per mostrare dove si trova la mia tela bianca, posso utilizzare CSS per lo stile, così io aggiungo una linea tratteggiata blu intorno l'elemento vuoto.

canvas {
    border-width: 5px;
    border-style: dashed;
    border-color: rgba(20, 126, 239, 0.50)
}

Il risultato, quando la mia pagina è aperto in Internet Explorer 9++, Chrome, Firefox, Opera o Safari, è raffigurato in Figura 1.

A Blank, Styled Canvas Element
Figura 1 in bianco, in stile elemento Canvas

Quando si utilizza la tela, che farete la maggior parte del vostro lavoro in JavaScript, dove le API esposte di un contesto di disegno di tela possono essere sfruttate per manipolare ogni pixel della superficie. Per ottenere il contesto di disegno di tela, è necessario ottenere l'elemento di tela dal DOM e quindi chiamare il metodo getContext di quell'elemento.

var _canvas = document.getElementById('chart');
var _ctx = _canvas.getContext("2d");

GetContext restituisce un oggetto con un'API che è possibile utilizzare per disegnare sulla tela in questione. Il primo argomento al metodo (in questo caso, "2d") specifica l'API di disegno che si desidera utilizzare per la tela. "2d" si riferisce al contesto 2D HTML Canvas accennato in precedenza. Come si può immaginare, 2D significa che questo è un contesto di disegno bidimensionale. Come di questa scrittura, il contesto 2D è il contesto di disegno ampiamente supportato solo, ed è quello che useremo per questo articolo. C'è il lavoro in corso e sperimentazione intorno a un contesto di disegno 3D, così tela dovrebbe fornire ancora più potenza per le nostre applicazioni in futuro.

Disegno di linee, forme e testo

Ora che abbiamo un elemento di tela sulla nostra pagina e noi abbiamo ottenuto il suo contesto di disegno in JavaScript, possiamo cominciare a aggiungere contenuto. Perché voglio concentrarmi sulla visualizzazione dei dati, ho intenzione di usare la tela per disegnare un grafico a barre per rappresentare i dati di vendita del mese corrente per un immaginario negozio di articoli sportivi. Questo esercizio richiederà linee di disegno per gli assi; forme e riempimenti per le barre; e il testo per le etichette su ogni asse e bar.

Cominciamo con le linee per gli assi x e y. Disegno di linee (o percorsi) con il contesto di tela è un processo in due fasi. In primo luogo, si "traccia" le linee sulla superficie utilizzando una serie di lineTo (x, y) e chiamate moveTo (x, y). Ogni metodo accetta le coordinate x e y-sull'oggetto di tela (a partire dall'angolo in alto a sinistra) da utilizzare quando si esegue l'operazione (in contrapposizione a coordinate sullo schermo stesso). Il metodo moveTo si muoverà alle coordinate si specifica e lineTo si traccia una linea da coordinate correnti alle coordinate specificate. Ad esempio, il codice seguente traccerà il nostro asse y sulla superficie:

// Draw y axis.
_ctx.moveTo(110, 5);
_ctx.lineTo(110, 375);

Se si aggiunge questo codice script ed eseguire nel browser, si noterà che nulla accade. Perché questo primo passo è semplicemente un passo di tracciatura, nulla viene disegnato sullo schermo. Tracciatura semplicemente istruisce il browser a prendere atto di un'operazione di percorso sarà essere svuotata sullo schermo a un certo punto in futuro. Quando io sono pronto a disegnare percorsi sullo schermo, facoltativamente, impostare la proprietà strokeStyle del mio contesto e quindi chiamare il metodo di ictus, che riempirà le linee invisibili. Il risultato è raffigurato in Figura 2.

 

// Define Style and stroke lines.
_ctx.strokeStyle = "#000";
_ctx.stroke();

A Single Line on the Canvas
Figura 2 singola riga sulla tela

Perché sono disaccoppiati definendo linee (lineTo, moveTo) e tracciare delle linee (ictus), puoi lotto in realtà una serie di operazioni lineTo e moveTo e poi uscita quelli sullo schermo tutti in una volta. Farò questo per gli assi x e y - sia per le operazioni che disegnare frecce come la fine di ogni asse. La funzione completa per disegnare gli assi è mostrata in Figura 3 e il risultato in Figura 4.

Figura 3 drawAxes funzione

function drawAxes(baseX, baseY, chartWidth) {
   var leftY, rightX;
   leftY = 5;
   rightX = baseX + chartWidth;
   // Draw y axis.
   _ctx.moveTo(baseX, leftY);
   _ctx.lineTo(baseX, baseY);
   // Draw arrow for y axis.
   _ctx.moveTo(baseX, leftY);
   _ctx.lineTo(baseX + 5, leftY + 5);
   _ctx.moveTo(baseX, leftY);
   _ctx.lineTo(baseX - 5, leftY + 5);
   // Draw x axis.
   _ctx.moveTo(baseX, baseY);
   _ctx.lineTo(rightX, baseY);
   // Draw arrow for x axis.
   _ctx.moveTo(rightX, baseY);
   _ctx.lineTo(rightX - 5, baseY + 5);
   _ctx.moveTo(rightX, baseY);
   _ctx.lineTo(rightX - 5, baseY - 5);
   // Define style and stroke lines.
   _ctx.strokeStyle = "#000";
   _ctx.stroke();
}

Completed X- and Y-Axes
Figura 4 completato assi x e y

Abbiamo i nostri assi, ma probabilmente dovremmo etichettarle per renderli più utile. Il contesto di tela 2D specifica API per l'aggiunta di testo a tela elementi, così non hai bisogno di giocherellare con incisioni disordinati come galleggianti di testo sopra l'elemento canvas. Detto questo, testo di tela non fornisce un modello di scatola, né riconosce gli stili CSS definiti per testo a livello di pagina e così via. L'API fornisce un attributo di tipo di carattere che funziona come una regola di font CSS — così come proprietà textAlign e textBaseline per darvi qualche controllo sulla posizione relative alle coordinate fornite — ma diverso da quello, disegno di testo sulla tela è una questione di prendersela con la tela per il testo è fornire un punto esatto.

L'asse x rappresenta prodotti nel nostro negozio di articoli sportivi immaginario, così noi dovremmo etichetta quell'asse di conseguenza:

var height, widthOffset;
height = _ctx.canvas.height;
widthOffset = _ctx.canvas.width/2;
_ctx.font = "bold 18px sans-serif";
_ctx.fillText("Product", widthOffset, height - 20);

In questo frammento di codice, sono l'impostazione della proprietà del tipo di carattere facoltativo e fornendo una stringa per disegnare sulla superficie, insieme con le coordinate x e y-da utilizzare come posizione di inizio della stringa. In questo esempio, I'll trarre la parola "Prodotto" nel mezzo della mia tela, 20 pixel fino dal basso, che lascia spazio per le etichette per ogni prodotto sul mio grafico a barre. Farò qualcosa di simile per l'etichetta dell'asse y, che contiene i dati di vendita per ogni prodotto. Il risultato è raffigurato in Figura 5.

Canvas with Text
Figura 5 tela con testo

Ora che abbiamo un quadro per il nostro grafico, possiamo aggiungere le barre. Creiamo alcuni dati di vendita fittizi per il grafico a barre, che definirò come matrice di valori letterali oggetto JavaScript.

var salesData = [{
   category: "Basketballs",
   sales: 150
}, {
   category: "Baseballs",
   sales: 125
}, {
   category: "Footballs",
   sales: 300
}];

Con questi dati in mano, possiamo utilizzare fillRect e fillStyle per disegnare i nostri bar sul grafico.

fillRect (x, y, width, height) disegneranno un rettangolo sulla tela presso le coordinate x e y-, con la larghezza e l'altezza specificate. È importante notare che fillRect disegna forme a partire dall'alto a sinistra che si irradia verso l'esterno, a meno che non si specificano i valori width e height negativi, nel qual caso il riempimento si irradia in direzione opposta. Per disegno compiti come grafici, significa che ci sarà essere disegno le barre dall'alto verso il basso, al contrario di basso verso l'alto.

Per disegnare le barre, possiamo scorrere la matrice di dati sulle vendite e chiamare fillRect con le coordinate appropriate:

var i, length, category, sales;
var barWidth = 80;
var xPos = baseX + 30;
var baseY = 375;       
for (i = 0, length = salesData.length; i < length; i++) {
   category = salesData[i].category;
   sales = salesData[i].sales;
   _ctx.fillRect(xPos, baseY - sales-1, barWidth, sales);
   xPos += 125;
}

In questo codice, la larghezza di ogni barra è standard, mentre l'altezza è preso dalla proprietà vendite per ogni prodotto nella matrice. Il risultato di questo codice è visto Figura 6.

Rectangles as Bar Chart Data
Figura 6 rettangoli come dati grafico a barre

Ora, abbiamo un grafico che è tecnicamente accurato, ma quelle solide barre nere lasciano un po' a desiderare. Cerchiamo di abete con qualche colore e quindi aggiungere un effetto sfumato.

Lavorando con colori e sfumature

Quando viene chiamato il metodo fillRect di un contesto di disegno, il contesto utilizzerà la proprietà fillStyle corrente per il rettangolo come suo disegnato in stile. Lo stile predefinito è un solido nero, motivo per cui il nostro grafico sembra come fa in Figura 6. fillStyle accetta denominato, esadecimale e colori RGB, quindi cerchiamo di aggiungere alcune funzionalità per definire lo stile ogni barra prima che esso viene disegnato:

// Colors can be named hex or RGB.
colors = ["orange", "#0092bf", "rgba(240, 101, 41, 0.90)"];       
...
_ctx.fillStyle = colors[i % length];
_ctx.fillRect(xPos, baseY - sales-1, barWidth, sales);

In primo luogo, creiamo una matrice di colori. Poi, come abbiamo scorrere in ogni prodotto, useremo uno di questi colori come lo stile di riempimento per quell'elemento. Il risultato è raffigurato in Figura 7.

Using fillStyle to Style Shapes
Figura 7 Using fillStyle alle forme di stile

Questo sembra migliore, ma fillStyle è molto flessibile e consente di utilizzare i gradienti radiali e lineare invece di colori solo solidi. Il contesto di disegno 2D specifica due funzioni di gradiente, createLinerGradient e createRadialGradient, entrambi i quali possono migliorare lo stile del vostro forme attraverso le transizioni di colore uniforme.

Per questo esempio, vado per definire una funzione createGradient che accetterà le coordinate x e y per la sfumatura, una larghezza e il colore primario da utilizzare:

function createGradient(x, y, width, color) {
   var gradient;
   gradient = _ctx.createLinearGradient(x, y, x+width, y);
   gradient.addColorStop(0, color);
   gradient.addColorStop(1, "#efe3e3");
   return gradient;
}

Dopo la chiamata a createLinearGradient con il mio coor start ed end­dinates, I'll aggiungere due fermate di colore per il gradiente oggetto restituito dal contesto del disegno. Il metodo addColorStop aggiunge transizioni di colore lungo il gradiente; si può chiamare qualsiasi numero di volte con valori di parametro primi tra 0 e 1. Una volta ho impostato il mio gradiente, la tornerò dalla funzione.

L'oggetto gradiente può essere impostato come la proprietà fillStyle su mio contesto, al posto del hex e stringhe RGB specificato nell'esempio precedente. Potrai utilizzare quegli stessi colori come punto di partenza e poi li svanire in un grigio chiaro.

colors = ["orange", "#0092bf", "rgba(240, 101, 41, 0.90)"];
_ctx.fillStyle = createGradient(xPos, baseY - sales-1, barWidth, colors[i % length]);
_ctx.fillRect(xPos, baseY - sales-1, barWidth, sales);

Il risultato dell'opzione gradiente può essere visto Figura 8.

Using Gradients in a Canvas
Figura 8 utilizzo di gradienti in una tela

Lavorare con immagini

A questo punto, abbiamo un abbastanza bell'aspetto grafico, che siamo stati in grado di eseguire il rendering nel browser mediante poche decine di righe di JavaScript. Potrei smettere di qui, ma c'è ancora una base tela API correlate a lavorare con le immagini che voglio coprire. Non solo fa tela farvi sostituire immagini statiche con basati su script e contenuti interattivi, ma è anche possibile utilizzare immagini statiche per migliorare la tuo tela effetti grafici.

Per questa demo, vorrei utilizzare immagini come le barre sul grafico a barre. E non appena le eventuali immagini, ma immagini degli oggetti stessi. Con questo obiettivo in mente, il mio sito Web ha una cartella contenente immagini JPG per ogni prodotto — in questo caso, basketballs.jpg, baseballs.jpg e footballs.jpg. Tutto quello che ho bisogno di fare è posizione e dimensioni ogni immagine in modo appropriato.

Il contesto di disegno 2D definisce un metodo drawImage con tre overload, accettando di tre, cinque o nove parametri. Il primo parametro è sempre l'immagine di elemento DOM per disegnare. La versione più semplice di drawImage inoltre accetta le coordinate x e y-sulla tela e disegna l'immagine come è in quella posizione. È inoltre possibile fornire i valori di larghezza e altezza come gli ultimi due parametri, che scalerà l'immagine di quella dimensione prima di disegnarla sulla superficie. Infine, l'uso più complessa di drawImage consente di ritagliare un'immagine verso il basso per un rettangolo definito, scala di un dato insieme di dimensioni e, infine, disegnarlo sulla tela a coordinate specificate.

Poiché le immagini sorgente che ho sono su larga scala immagini utilizzate altrove sul mio sito, ho intenzione di prendere l'approccio di quest'ultimo. In questo esempio, piuttosto che chiamare la fillRect per ogni elemento, come scorrere la matrice salesData, creerò un elemento DOM di immagine, impostare la sua sorgente a una delle mie immagini di prodotto che il rendering di una versione ritagliata di quell'immagine sul mio grafico, come Figura 9 mostra.

Figura 9 immagini di disegno su tela

// Set outside of my loop.
xPos = 110 + 30;     
// Create an image DOM element.
img = new Image();
img.onload = (function(height, base, currentImage, currentCategory) {
  return function() {
    var yPos, barWidth, xPos;
    barWidth = 80;
      yPos = base - height - 1;
    _ctx.drawImage(currentImage, 30, 30, barWidth, height, xPos, yPos,
      barWidth, height);
      xPos += 125;           
  }
})(salesData[i].sales, baseY, img, salesData[i].category);
img.src = "images/" + salesData[i].category + ".jpg";

Perché sto creando queste immagini in modo dinamico, al contrario di aggiungerli manualmente al mio markup in fase di progettazione, non dovrei presumo che posso impostare l'origine dell'immagine, quindi disegnare immediatamente quell'immagine a mia tela. Per garantire che traggo ogni immagine solo quando è completamente caricato, aggiungerò il mio disegno logica per l'evento onload per l'immagine, poi avvolgere quel codice in una funzione self-invoking, che crea una chiusura con variabili che puntano alla categoria di prodotto corretto, le variabili di vendite e posizionamento. Potete vedere il risultato in Figura 10.

Using Images on a Canvas
Figura 10 utilizzando immagini su tela

Utilizzando una tela Polyfill

Come forse sapete, versioni di Internet Explorer prima di 9, così come le versioni precedenti di altri browser, non supportano l'elemento canvas. È possibile visualizzare questo per te il progetto demo di apertura in Internet Explorer e premendo F12 per aprire gli strumenti di sviluppo. Dagli strumenti F12, puoi modificare la modalità di Browser Internet Explorer 8 o Internet Explorer 7 e aggiornare la pagina. Che cosa è molto probabile che vedere è un'eccezione di JavaScript con il messaggio "oggetto non supporta la proprietà del metodo getContext." Il contesto di disegno 2D non è disponibile, né è l'elemento di tela. È anche importante sapere che, anche in Internet Explorer 9, non tela è disponibile a meno che non si specifica un DOCTYPE. Come ho già detto nel primo articolo di questa serie (msdn.microsoft.com/magazine/hh335062), è sempre una buona idea usare <!DOCTYPE html > nella parte superiore del tutto il tuo codice HTML pagine per assicurare che le ultime caratteristiche nel browser sono disponibili.

Corso d'azione che si può prendere per gli utenti cui browser non supporta la tela più semplice è quello di utilizzare un elemento fallback come immagine o testo. Per esempio, per visualizzare un'immagine di fallback agli utenti, è possibile utilizzare markup che assomiglia a questo:

<canvas id=”chart”>
  <img id=”chartIMG” src=”images/fallback.png”/>
</canvas>

Qualsiasi contenuto che si inserisce all'interno di <canvas> Tag verrà eseguito il rendering solo se il browser dell'utente non supporta la tela. Ciò significa che è possibile inserire immagini o testo all'interno della tua tela come ripiego zero-controlli semplici, per gli utenti.

Se si desidera prendere il fallback supporto ulteriormente, la buona notizia è che una varietà di soluzioni polyfilling esistere per tela, così si può sentire comodo usando con browser meno recenti, purché attentamente veterinario potenziali soluzioni e rimanere consapevoli dei limiti di un dato polyfill. Come ho già detto in altri articoli di questa serie, il vostro punto di partenza per trovare un polyfill per qualsiasi tecnologia di HTML5 dovrebbe essere la pagina HTML5 Cross Browser Polyfills nel wiki Modernizr su GitHub (bit.ly/nZW85d). Redazione di questo, ci sono parecchi tela polyfills disponibili, tra cui due che ripiegare a Flash e Silverlight.

Nel progetto demo scaricabile per questo articolo, io uso explorercanvas (code.google.com/p/explorercanvas), che viene supportato da Internet Explorer Vector Markup Language (VML) per creare strette approssimazioni di funzionalità di tela e testo di tela (code.google.com/p/canvas-text), che aggiunge il supporto supplementare per il testo di rendering in browser meno recenti.

Come illustrato negli articoli precedenti, è possibile utilizzare Modernizr per caratteristica-rilevare il supporto per la tela (e canvastext) in un browser chiamando Modernizr.canvas e quindi utilizzare Modernizr.load per caricare in modo asincrono explorercanvas quando necessario. Per ulteriori informazioni, vedere modernizr.com.

Se non si desidera utilizzare Modenrizr, c'è un altro modo per aggiungere in modo condizionale explorercanvas per le versioni precedenti di IE: commenti condizionali:

<!--[if lt IE 9]>
  <script src="js/excanvas.js"></script>
  <script src="js/canvas.text.js"></script>
<![endif]-->

Quando Internet Explorer 8 o versioni precedenti incontrano un commento formattato come tale, si eseguirà il blocco come se istruzione e includere i file di script explorercanvas e testo di tela. Altri browser, tra cui Internet Explorer 10, sarà trattare l'intero blocco come un commento e ignora del tutto.

Quando si valuta un potenziale polyfill per la vostra applicazione, assicurarsi di guardare in quanto del contesto del disegno 2D supporta un dato polyfill. Pochi di loro fornire supporto completo per ogni uso, anche se quasi tutti in grado di gestire i casi di base che abbiamo guardato in questo articolo.

Anche se non potevo coprire a tutto qui, non c'è molto di più si può fare con tela, da rispondendo al clic (e altre) eventi e mutevoli dati della tela, animando il disegno superficiale, rendering e manipolare immagini di-pixel, salvataggio dello stato ed esportazione l'intera superficie come la propria immagine. In realtà, ci sono interi libri su tela là fuori. Non dovete essere uno sviluppatore di gioco per sperimentare la potenza della tela, e spero che convinto che come ho camminato attraverso le basi in questo articolo. Vi incoraggio a leggere le specifiche per te stesso e saltare dentro a questa eccitante nuova tecnologia grafica con entrambi i piedi.

Se stai cercando per ulteriori informazioni sul supporto di tela in Internet Explorer 9, check out IE9 Developer Guide on-line (msdn.microsoft.com/ie/ff468705). Inoltre, essere sicuri di controllare le demo Canvas Pad disponibile presso il sito di IE Test Drive (bit.ly/9v2zv5). Per un elenco di alcuni altri polyfills cross-browser per tela, controlla l'elenco completo polyfilling a (bit.ly/eBMoLW).

Infine, tutte le demo per questo articolo — che sono disponibili online — furono costruiti usando WebMatrix, uno strumento di sviluppo a Web che leggero, libero da Microsoft. È possibile provare WebMatrix per te a aka.ms/webm.

Brandon Satrom funziona come un developer evangelist per Microsoft di fuori di Austin. Ha blog a userinexperience.com e lo potete seguire su Twitter a twitter.com/BrandonSatrom.

Grazie ai seguenti esperti tecnici per la revisione di questo articolo: Jatinder Mann e Clark Sell