In questo articolo, ti illustrerò le trasformazioni nella tela, oltre alle ombre e ai gradienti. Le trasformazioni sono un insieme di metodi estremamente prezioso che ti consente di iniziare a essere creativo con il modo in cui disegni gli oggetti sulla tela. Iniziamo dopo il salto!
Utilizzerai lo stesso modello HTML degli articoli precedenti, quindi apri il tuo editor preferito e incolla il seguente codice:
Tela da zero
Qui non abbiamo nient'altro che una pagina HTML di base con a tela
elemento e alcuni JavaScript che vengono eseguiti dopo il caricamento del DOM. Niente di pazzo.
Traduci essenzialmente sposta l'intero sistema di coordinate.
Una delle più semplici trasformazioni nella tela è tradurre
. Ciò consente di spostare il punto di origine del contesto di rendering 2D; la posizione (0, 0) sulla tela. Lascia che ti mostri cosa significa.
Innanzitutto, posiziona un quadrato su tela nella posizione (0, 0):
ctx.fillRect (0, 0, 100, 100);
Si disegnerà sul bordo in alto a sinistra della tela. Ancora - niente di straordinario qui.
Ora provate a tradurre il contesto di rendering 2D e disegnate un altro quadrato nella stessa posizione:
ctx.save (); ctx.translate (100, 100); ctx.fillStyle = "rgb (0, 0, 255)"; ctx.fillRect (0, 0, 100, 100); ctx.restore ();
Cosa pensi che succederà? Avere una stella d'oro se si indovina che il nuovo quadrato verrà disegnato nella posizione (100, 100). Nessun tempo di gioco per chi ha sbagliato. scusate!
Quindi cosa è successo qui allora? Per quanto riguarda il codice per disegnare il secondo quadrato, lo hai disegnato nello stesso punto del primo quadrato. La ragione di ciò è che in pratica hai spostato l'intero sistema di coordinate della tela in modo che la sua posizione (0, 0) sia ora nel luogo (100, 100).
Ha un po 'più senso ora? Lo spero. Ci vuole un po 'di tempo per capire, ma è un concetto semplice una volta capito.
Probabilmente non useresti questa trasformazione troppo da sola, dato che potresti semplicemente disegnare il secondo quadrato a (100, 100) per ottenere lo stesso effetto. La bellezza di tradurre
, tuttavia, è possibile combinarlo con altre trasformazioni per fare cose interessanti.
Diamo un'occhiata alla prossima trasformazione nell'elenco.
Come probabilmente hai indovinato, il scala
la trasformazione è utilizzata per il ridimensionamento. Più in particolare, la trasformazione della scala viene utilizzata per ridimensionare il contesto di rendering 2D.
Rimuovi il codice con cui hai lavorato tradurre
esempio e aggiungi il seguente codice:
ctx.fillRect (100, 100, 100, 100);
Questo disegnerà un quadrato standard nella posizione (100, 100), con una larghezza e un'altezza di 100 pixel. Quindi, come lo scaliamo?
Le proprietà in scala sono moltiplicatori per le dimensioni x e y.
Il scala
la trasformazione è usata in modo simile a tradurre
, in quanto viene chiamato prima di disegnare gli oggetti a cui vuoi che venga applicato. È importante sottolineare che le proprietà in scala
sono moltiplicatori per il X e y dimensioni. Ciò significa che a scala
di (1, 1) moltiplicherebbe la dimensione del contesto di rendering 2d di uno, lasciandolo delle stesse dimensioni precedenti. UN scala
di (5, 5) moltiplicherebbe la dimensione del contesto di rendering 2d per cinque, rendendolo cinque volte più grande di prima. Semplice.
Nel tuo caso vuoi raddoppiare la dimensione del quadrato, quindi applichi a scala
di (2, 2):
ctx.save (); ctx.scale (2, 2); ctx.fillRect (100, 100, 100, 100); ctx.restore ();
Il che risulta in un quadrato che è due volte la dimensione:
Tuttavia, nota come il quadrato viene disegnato in una posizione diversa da quella che veniva disegnata prima di applicare scala
. La ragione di questo è quello scala
moltiplica le dimensioni di tutto nel contesto di rendering 2D, incluse le coordinate. Nel tuo caso, la posizione (100, 100) diventa ora (200, 200); le coordinate sono il doppio delle dimensioni che sarebbero senza essere ridimensionate.
Per aggirare questo, possiamo eseguire a tradurre
che sposta l'origine del contesto di rendering 2D alla posizione in cui si desidera disegnare il quadrato. Se poi si applica scala
e disegna il quadrato in posizione (0, 0), la sua posizione non sarà spostata:
ctx.save (); ctx.translate (100, 100); ctx.scale (2, 2); ctx.fillRect (0, 0, 100, 100); ctx.restore ();
Il che risulta in un quadrato che è due volte più grande dell'originale, ma che viene disegnato nella stessa posizione dell'originale:
È consapevole di questi piccoli capricci nelle trasformazioni che aiutano davvero quando li usano. La maggior parte dei problemi comuni con le trasformazioni sembra essere il risultato di non comprendere completamente come funzionano.
Finora, tutte le trasformazioni con cui hai avuto a che fare sono state piuttosto poco eccitanti. Fortunatamente, il ruotare
la trasformazione è qui per salvare il giorno, ed è facilmente il mio preferito del gruppo.
sono sicuro ruotare
non ha bisogno di presentazioni, quindi saltiamo a destra e ruotiamo un quadrato di 45 gradi (ricorda che i gradi devono essere in radianti):
ctx.save (); ctx.rotate (Math.PI / 4); // Ruota di 45 gradi (in radianti) ctx.fillRect (100, 100, 100, 100); ctx.restore ();
Quale posiziona un quadrato a (100, 100) e ruota? woah, aspetta! Questo non sembra giusto:
Vedi cosa è successo? Sembra che il quadrato stia cercando di uscire dalla finestra del browser, piuttosto che ruotare sul posto nella posizione (100, 100). Questo è perché ruotare
, come tutte le trasformazioni, influenza l'intero contesto di rendering 2D e non gli oggetti individualmente.
Ecco un'illustrazione di cosa succede al sistema di coordinate quando esegui un 45 gradi ruotare
:
Notare come l'intero sistema di coordinate ha ruotato di 45 gradi dal punto di origine (0, 0)? Questo è ciò che ha fatto apparire il quadrato come se fuggisse dalla finestra del browser, semplicemente perché la posizione (100, 100) era stata ruotata sul bordo del browser.
Il modo più semplice per aggirare questo problema è combinare ruotare
con tradurre
, così:
ctx.save (); ctx.translate (150, 150); // Traduci al centro di piazza ctx.rotate (Math.PI / 4); // Ruota di 45 gradi ctx.fillRect (-50, -50, 100, 100); // Centra il punto di rotazione ctx.restore ();
Esecuzione del tradurre
sposta il punto di origine del contesto di rendering 2D (0, 0) in quello che dovrebbe essere il punto centrale del quadrato (150, 150). Ciò significa che qualsiasi rotazione ora sarà basata attorno alla posizione (150, 150). Se quindi si disegna un quadrato con un negativo X e y posizione, pari alla metà della larghezza e dell'altezza del quadrato, finirai per disegnare un quadrato che sembra essere stato ruotato attorno al suo punto centrale:
Il ruotare
la trasformazione è probabilmente la più difficile da comprendere per tutti. È importante ricordare che le trasformazioni vengono eseguite nell'intero contesto di rendering 2D e, se si desidera ruotare una forma attorno al suo punto centrale, è necessario combinare ruotare
con tradurre
.
Passiamo a qualcosa di un po 'più visivamente impressionante.
Aggiungere ombre agli oggetti è deliziosamente semplice.
Canvas viene fornito con alcune proprietà per manipolare l'aspetto degli oggetti disegnati su di esso e un set di queste proprietà consente di aggiungere ombre.
Aggiungere ombre agli oggetti è deliziosamente semplice. Richiede semplicemente il shadowColor
proprietà da impostare nel contesto di rendering 2D a un colore che non è nero trasparente e uno dei due shadowBlur
, shadowOffsetX
, o shadowOffsetY
proprietà da impostare su un valore diverso da 0.
Prova il seguente codice:
ctx.save (); ctx.shadowBlur = 15; ctx.shadowColor = "rgb (0, 0, 0)"; ctx.fillRect (100, 100, 100, 100); ctx.restore ();
Ciò conferirà all'ombra una sfocatura di quindici pixel e imposterà il colore sul nero uniforme:
Cose abbastanza standard finora.
Se imposti il shadowBlur
a 0, cambia il shadowColor
ad un grigio chiaro, e dare un positivo shadowOffsetX
e shadowOffsetY
:
ctx.save (); ctx.shadowBlur = 0; ctx.shadowOffsetX = 6; ctx.shadowOffsetY = 6; ctx.shadowColor = "rgba (125, 125, 125, 0.5)"; // Transparent gray ctx.fillRect (300, 100, 100, 100); ctx.restore ();
Finirai con un'ombra solida che appare leggermente a destra e sotto l'oggetto che è stato disegnato:
Per quanto fredde siano le ombre, possono essere un po 'un maiale da risorsa.
È importante ricordare che le ombre influenzano tutto ciò che viene disegnato dopo che sono state definite, quindi è utile usare il salvare
e ristabilire
metodi per evitare di dover reimpostare le proprietà delle ombre dopo averle utilizzate.
Tieni presente che le prestazioni possono risentire quando stai applicando un'ombra a molti e tanti oggetti allo stesso tempo. In alcuni casi, potrebbe valere la pena di usare un'immagine PNG con un'ombra invece di disegnare manualmente un oggetto e applicare un'ombra dinamica usando il codice. Tratteremo come utilizzare le immagini con la tela nella prossima puntata di questa serie.
Puoi creare due tipi di sfumature in tela: lineare e radiale.
Le ultime funzionalità che voglio illustrare in questo tutorial sono le sfumature. Ci sono due tipi di gradienti nella tela, i primi sono gradienti lineari (diritti). Puoi creare un gradiente lineare usando il createLinearGradient
metodo (abbastanza sorprendentemente), che assomiglia a questo in pseudo-codice:
ctx.createLinearGradient (startX, startY, endX, endY);
Il primo gruppo di due argomenti è il X e y posizione dell'inizio del gradiente e il secondo insieme di argomenti è il X e y posizione della fine del gradiente. È anche importante sottolineare che un gradiente nella tela è in realtà un tipo di valore del colore, quindi li si applica a fillStyle
e strokeStyle
proprietà.
Ecco un esempio di come creare un gradiente lineare che vada dalla parte superiore della tela, fino alla fine:
var gradient = ctx.createLinearGradient (0, 0, 0, canvas.height); gradient.addColorStop (0, "rgb (255, 255, 255)"); gradient.addColorStop (1, "rgb (0, 0, 0)"); ctx.save (); ctx.fillStyle = gradient; ctx.fillRect (0, 0, canvas.width, canvas.height); ctx.restore ();
Si noti come si assegna il gradiente a una variabile, quindi si usa quella variabile per chiamare il addColorStop
metodo. Questo metodo ti consente di impostare il colore in punti particolari lungo il gradiente. Ad esempio, la posizione 0 rappresenterebbe l'inizio del gradiente (il primo X e y posizione), e 1 rappresenterebbe la fine del gradiente (il secondo X e y posizione). Puoi anche usare i punti decimali tra 0 e 1 per assegnare un colore in un punto diverso lungo il gradiente, come 0.5 sarebbe a metà strada lungo.
Applicando la variabile del gradiente al fillStyle
proprietà, si finisce con un gradiente gradevole che va dal bianco (nella posizione 0 nella parte superiore della tela), al nero (nella posizione 1 nella parte inferiore della tela):
Ma non devi sempre usare gradienti lineari; puoi anche creare sfumature radiali!
I gradienti radiali sono creati con il createRadialGradient
metodo, che assomiglia a questo in pseudo-codice:
ctx.createRadialGradient (startX, startY, startRadius, endX, endY, endRadius);
Il primo gruppo di tre argomenti è il X e y posizione e il raggio del cerchio all'inizio del gradiente, con gli ultimi tre argomenti che rappresentano il X e y posizione così come il raggio del cerchio alla fine del gradiente.
Suona confuso, giusto? È un po ', quindi saltiamo dentro e creiamo un gradiente radiale per vedere cosa succede:
var gradient = ctx.createRadialGradient (350, 350, 0, 50, 50, 100); gradient.addColorStop (0, "rgb (0, 0, 0)"); gradient.addColorStop (1, "rgb (125, 125, 125)"); ctx.save (); ctx.fillStyle = gradient; ctx.fillRect (0, 0, canvas.width, canvas.height); ctx.restore ();
Hai creato un gradiente radiale che ha un punto iniziale a (350, 350) con un raggio di 0 e un punto finale a (50, 50) con un raggio di 100. Puoi indovinare come sarà? 20 punti se hai indovinato sarebbe simile a questo:
Se sei come me, non è quello che mi aspettavo di vedere. Ho usato gradienti radiali prima in applicazioni come Adobe Photoshop, e non sembrano niente del genere! Allora perché sembra così? Bene, questo è quello che dovrebbe sembrare, stranamente.
Dai uno sguardo a questo diagramma che illustra esattamente come funziona una sfumatura radiale nella tela:
Interessante, non è vero? In pratica ti permette di creare una forma conica, ma cosa succede se vuoi creare un gradiente radiale adeguato come quello di Photoshop? Fortunatamente, è semplice.
Creare un gradiente radiale appropriato richiede semplicemente di posizionare i due cerchi del gradiente esattamente allo stesso modo X e y posizione, assicurandosi che uno dei cerchi sfumati sia più grande dell'altro:
var canvasCentreX = canvas.width / 2; var canvasCentreY = canvas.height / 2; var gradient = ctx.createRadialGradient (canvasCentreX, canvasCentreY, 250, canvasCentreX, canvasCentreY, 0); gradient.addColorStop (0, "rgb (0, 0, 0)"); gradient.addColorStop (1, "rgb (125, 125, 125)"); ctx.save (); ctx.fillStyle = gradient; ctx.fillRect (0, 0, canvas.width, canvas.height); ctx.restore ();
Il codice sopra crea una sfumatura radiale che si trova al centro della tela. Uno dei cerchi nel gradiente ha un raggio di 0, mentre l'altro ha un raggio di 250. Il risultato è un tradizionale gradiente radiale che viaggia dal centro della tela verso l'esterno, in questo modo:
Sembra migliore! Sono stato sinceramente stupito quando ho visto come le sfumature radiali sono state implementate sulla tela. Scommetto che ha fatto inciampare molte persone quando vedono quella forma di cono. Oh bene, almeno sai come creare quelli giusti adesso.
Vale la pena sottolineare che i gradienti nella tela sono anche operazioni piuttosto intensive. Se vuoi coprire l'intero canvas con un gradiente, dovrei prima considerare di applicare uno sfondo gradiente CSS3 all'elemento canvas stesso.
In questo articolo, abbiamo esaminato come eseguire trasformazioni di base sull'area di disegno, comprese le traduzioni, il ridimensionamento e la rotazione. Hai anche imparato come aggiungere ombre agli oggetti e come creare sfumature. Non sembra molto, ma le trasformazioni, in particolare, costituiscono la spina dorsale di alcune delle cose più interessanti che si possono ottenere su tela.
Nella prossima voce in "Canvas from Scratch", ci separeremo dal disegnare oggetti e daremo un'occhiata a come manipolare immagini e video nell'area di disegno. È qui che le cose iniziano a diventare davvero interessanti! Rimanete sintonizzati!