Canvas From Scratch disegno avanzato

Nel precedente articolo di questa serie, hai imparato a conoscere l'elemento canvas e le basi per disegnarlo. In questo articolo, ho intenzione di dimostrare alcune delle funzionalità di disegno più avanzate.


Impostare

Useremo lo stesso modello HTML dal precedente articolo; quindi apri il tuo editor preferito e incolla il seguente codice:

    Tela da zero          

Questo non è altro che una semplice pagina HTML con a tela elemento e alcuni JavaScript che vengono eseguiti dopo il caricamento del DOM. Niente di pazzo.


Disegnare cerchi

Nell'ultimo articolo ti ho mostrato come disegnare forme e percorsi di base; in questa sezione ti mostrerò come fare un passo avanti e disegnare cerchi. Non è così facile come potresti pensare, ma non è affatto difficile.

Non esiste un metodo su tela che ti consenta di disegnare un cerchio con una singola riga di codice, come come fillRect funziona per i rettangoli. Invece, devi disegnare cerchi con un percorso usando il arco metodo; un cerchio è semplicemente un arco a 360 gradi. La ragione di ciò è che i cerchi sono in realtà forme molto complesse e il arco il metodo consente tutti i tipi di controllo sul modo in cui li disegni. Ad esempio, potresti voler disegnare solo un semicerchio. Il arco metodo ti permette di farlo. Potresti anche combinare il arco metodo con percorsi standard dritti per disegnare fette di pizza e quarti di cerchio.

Ti spiego come arco metodo funziona a breve, ma per ora, disegniamo un cerchio aggiungendo il seguente codice sotto il CTX variabile:

 cxt.beginPath (); ctx.arc (100, 100, 50, 0, Math.PI * 2, falso); ctx.closePath (); ctx.fill ();

Questo disegnerà un cerchio posizionato leggermente lontano dalla parte superiore sinistra della tela:

Sembra semplice, giusto? E lo è, ma diamo un'occhiata più da vicino a cosa sta succedendo.

Il arco il metodo ha un totale di sei argomenti:

  • Il primo è il X posizione del punto di origine (il centro del cerchio).
  • Il secondo è il y posizione del punto di origine.
  • Il terzo è il raggio del cerchio.
  • Il quarto è l'angolo iniziale del cerchio.
  • Il quinto è l'angolo finale del cerchio.
  • E sesta è la direzione per disegnare l'arco (vero è antiorario, e falso è in senso orario)

Scritto in pseudocodice, arco sarebbe simile a questo:

 arco (x, y, raggio, startAngle, endAngle, antiorario);

I primi tre argomenti sono autoesplicativi, come l'ultimo, ma per quanto riguarda l'angolo iniziale e finale? Lasciatemi spiegare.

Come ho già detto, i cerchi sono solo archi a 360 gradi. Nella tela, un arco è definito come una linea curva che inizia a una distanza da un punto di origine che è la distanza del raggio. La linea curva inizia con l'angolo definito come l'argomento dell'angolo iniziale (il quarto avanti) e continua lungo la circonferenza di un cerchio immaginario fino a raggiungere l'angolo definito come argomento dell'angolo finale (il quinto). Sembra semplice, giusto?

Forse un'illustrazione aiuterà a spiegare la situazione:

Può sembrare pazzesco, ma ha molto senso una volta che riesci a capirlo.

Angoli in tela

A questo punto, probabilmente vale la pena ricordare che gli angoli nella tela sono fatti in radianti, non in gradi. Ciò significa che gli angoli vanno da 0 a pi moltiplicati per due. Anche gli angoli nella tela iniziano dal lato destro, come si può vedere nella figura seguente:

Se davvero non ti piacciono i radianti, puoi convertire facilmente i gradi in radianti con la seguente formula JavaScript:

 var gradi = 270; var radians = degrees * (Math.PI / 180);

Questa formula è semplice ed estremamente preziosa se vuoi affrontare i gradi.


B? Zier Percorsi

Gli archi sono divertenti e tutti, ma sono piuttosto limitanti per il tipo di curve che possono essere create con la tela. Per qualcosa di più complesso, ti consigliamo di iniziare a guardare i metodi della curva B? Zier quadraticCurveTo, e bezierCurveTo. Questi metodi ti consentono di creare percorsi curvi con un raggio non centrale rispetto alla curva e anche di creare percorsi con più curve.

I percorsi B? Zier usano i punti di controllo per definire come e dove disegnare le curve. Per esempio, quadraticCurveTo ha un punto di controllo, mentre bezierCurveTo ha due. Controlla la seguente illustrazione per vedere come i punti di controllo influenzano il modo in cui viene disegnata una curva:

Se hai già utilizzato un'applicazione di disegno vettoriale come Adobe Illustrator, potresti già sentirti a tuo agio con questo tipo di curve.

Entriamo e creiamo un percorso quadratico B? Zier. Sostituisci il codice dell'arco con quanto segue:

 ctx.lineWidth = 8; ctx.beginPath (); ctx.moveTo (50, 150); ctx.quadraticCurveTo (250, 50, 450, 150); ctx.stroke ();

Questo disegnerà un tracciato curvo che assomiglia a quello a sinistra dell'illustrazione sopra:

Il quadraticCurveTo il metodo richiede quattro argomenti:

  • Il primo è il X posizione del punto di controllo.
  • Il secondo è il y posizione del punto di controllo.
  • Il terzo è il X posizione della fine del percorso.
  • E il quarto è il y posizione della fine del percorso.

Scritto in pseudocodice, quadraticCurveTo sarebbe simile a questo:

 quadraticCurveTo (cpx, cpy, x, y);

La posizione iniziale della curva è ovunque si trovi il percorso. Ad esempio, nel codice sopra hai spostato l'inizio del percorso chiamando il moveTo metodo.

Aumentiamo un livello e creiamo un percorso B? Zier cubico. Sostituisci il codice precedente con il seguente:

 ctx.lineWidth = 8; ctx.beginPath (); ctx.moveTo (50, 150); ctx.bezierCurveTo (150, 50, 350, 250, 450, 150); ctx.stroke ();

Questo disegnerà un tracciato curvo simile a quello a destra dell'illustrazione sopra:

Il bezierCurveTo il metodo accetta sei argomenti:

  • Il primo è il X posizione del primo punto di controllo.
  • Il secondo è il y posizione del primo punto di controllo.
  • Il terzo è il X posizione del secondo punto di controllo.
  • Il quarto è il y posizione del secondo punto di controllo.
  • Il quinto è il X posizione della fine del percorso.
  • E il sesto è il y posizione della fine del percorso.

Scritto è pseudocodice, bezierCurveTo sarebbe simile a questo:

 bezierCurveTo (cp1x, cp1y, cp2x, cp2y, x, y);

I loro percorsi B? Zier non sono straordinari, ma se combinati con percorsi normali o se usati più volte, i risultati possono essere piuttosto profondi. Ti permettono di creare ogni sorta di forme complicate e pazze su tela!

Potresti voler controllare il plug-in Ai-> Canvas per Adobe Illustrator che ti consente di esportare il tuo disegno vettoriale come codice canvas. È abbastanza pulito e ti farà risparmiare un sacco di tempo!


Stato di disegno

Nell'articolo precedente di questa serie, ho spiegato come modificare lo stile di riempimento e di tracciato dell'area di disegno, nonché come modificare la larghezza della linea. Uno dei problemi a cui prestare attenzione quando si cambiano queste proprietà è che sarà necessario modificare manualmente i colori e la larghezza della linea di nuovo, se si desidera il colore o la larghezza che si era originariamente. Fortunatamente, come sempre, c'è un modo migliore per farlo; si chiama stato del disegno.

Lo stato del disegno su tela è essenzialmente uno stack su cui è possibile salvare gli stili correnti e quindi ripristinarli in un secondo momento.

È un concetto deviously semplice, ma che ti permette di fare tanto quando pienamente compreso. Infatti, lo stato del disegno contiene una quantità enorme di informazioni visive sulla tela, come la matrice di trasformazione, la regione di ritaglio e le seguenti proprietà; globalAlpha, globalCompositeOperation, strokeStyle, fillStyle, larghezza della linea, Linecap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, font, textAlign, e TextBaseline. Molti di questi saranno nuovi per te, quindi non preoccuparti. Imparerai a conoscere le trasformazioni e altre cose divertenti come le ombre nel prossimo articolo.

Salvataggio dello stato del disegno

Usare lo stato di disegno è semplice, ma comprenderlo completamente può richiedere un po 'di tempo. Sostituisci il codice dall'ultima sezione con il seguente:

 ctx.fillStyle = "rgb (0, 0, 255)"; ctx.save (); ctx.fillRect (50, 50, 100, 100);

Questo è veramente tutto ciò che serve per salvare lo stato del disegno: una sola chiamata al salvare metodo. Te l'ho detto che era semplice!

Quello che sta succedendo qui è che stai cambiando lo stile di riempimento della tela in blu, quindi salvando lo stato del disegno, che spinge lo stato corrente nello stack di cui stavo parlando in precedenza. Per impostazione predefinita, la pila di stati del disegno è vuota.

È importante ricordare che lo stack funziona come una pila di fogli sulla scrivania; il primo oggetto in pila è in basso, con l'ultimo elemento in cima. Se vuoi tornare al primo elemento, devi prima rimuovere tutti gli elementi sopra di esso. Questo è noto come un primo nel sistema di ultima uscita, o ultimo nel primo, se si vuole guardarlo al contrario.

Ripristinare lo stato del disegno

Salvare lo stato del disegno è ottimo e tutto, ma in realtà usarlo di nuovo è un po 'più utile. Per farlo, userai il ristabilire metodo.

Aggiungi il seguente codice al codice sopra:

 ctx.fillStyle = "rgb (255, 0, 0)"; ctx.fillRect (200, 50, 100, 100);

Questo disegnerà un altro rettangolo sulla tela, ma questa volta in un colore diverso (rosso):

Tutte le cose piuttosto standard finora, ma cosa succede se si desidera tornare al colore blu e disegnare un altro rettangolo? Bene, puoi impostare lo stile di riempimento manualmente come blu, ma sarebbe noioso. Proviamo a utilizzare il metodo di ripristino e vediamo cosa succede.

Aggiungi il seguente codice:

 ctx.restore () ctx.fillRect (350, 50, 100, 100);

Questo disegnerà un altro rettangolo, ma questa volta con lo stile di riempimento originale:

Quanto è stato facile? La chiamata a ristabilire tirato fuori e rimosso l'ultimo stato di disegno che è stato aggiunto allo stack e quindi applicato all'area di disegno, risparmiando un sacco di tempo. Ok, beh, in questo esempio potrebbe non esserti risparmiato un sacco di tempo, ma avresti dovuto modificare tutti i tipi di proprietà e le trasformazioni eseguite sulla tela.

Utilizzo di più stati di disegno

Quindi sai come usare lo stato del disegno per una singola occorrenza, ma cosa succede se salvi più stati di disegno? Per gli occhi acuti potresti ricordare che mi sono riferito alla pila come una pila di carta; ultimo ad entrare, primo ad uscire. Vediamo come funziona in codice.

Aggiorna il codice precedente per salvare lo stato del disegno dopo aver impostato lo stile di riempimento su rosso:

 ctx.fillStyle = "rgb (0, 0, 255)"; ctx.save (); ctx.fillRect (50, 50, 100, 100); ctx.fillStyle = "rgb (255, 0, 0)"; ctx.save (); ctx.fillRect (200, 50, 100, 100); ctx.restore () ctx.fillRect (350, 50, 100, 100);

Anche se questo è praticamente lo stesso codice di prima, tutto sarà cambiato poiché l'ultimo stato di disegno aggiunto allo stack contiene lo stile di riempimento rosso:

Per ripristinare il primo stato (lo stile di riempimento blu), dovrai chiamare ristabilire per la seconda volta, quindi aggiungi il seguente codice:

 ctx.restore (); ctx.fillRect (50, 200, 100, 100);

Ciò estrae e rimuove il primo stato dalla pila e lo applica alla tela, dandoti uno stile di riempimento blu:

Utilizzando più stati di disegno come questo è possibile risparmiare un sacco di tempo. È piuttosto carino!


Avvolgere le cose

Spero di non aver passato troppo in fretta tutto questo. Alcuni dei concetti che abbiamo trattato sono piuttosto avanzati e ti incoraggio a rileggere l'articolo e a giocare con il codice per capire meglio cosa sta succedendo.

Nel prossimo articolo imparerai come eseguire le trasformazioni sulla tela e come usare ombre e gradienti. Tempi emozionanti!