DEV Community

Cover image for Canvas Javascript: Come disegnare immagini
Roberto
Roberto

Posted on

Canvas Javascript: Come disegnare immagini

Ci sono molteplici situazioni per il quale potremmo volere un'immagine sul canvas ad esempio se stiamo creando un videogioco e dobbiamo caricare sia gli sfondi che gli sprite o se volessiomo manipolare delle foto o applicare degli effetti grafici animati.
Per questo e per molte altre ragioni in questo articolo tratteremo come caricare un immagine e impareremo ad usare il metodo che ci da a disposizione il context del canvas.

Come ogni progetto bisogna inizializzarlo e richiamare i vari tool che ci da il contesto 2d, per questo vi rimando a questo articolo che spiega come farlo.

*La funzione che abbiamo a disposizione per 'disegnare' un immagine sul canvas è *

  • ctx.drawImage(immagine, x, y)

Questa è la forma base, composta con gli argomenti obbligatori, più avanti spiegheremo anche gli altri, ma andiamo per gradi e inziamo a vedere quelli base.

  • immagine: è la variabile nella quale abbiamo salvato l'immagine che abbiamo precendentemente caricato. Ho dedicato il prossimo paragrafo al giusto caricamento della foto.
  • x, y : sono le cordinate che posizionano l'immagine sul canvas, partendo dal vertice superiore sinistro dell'immagine.

Alt Text

CARICARE UN IMMAGINE

Come abbiamo visto, dobbiamo passare una variabile con l'immagine alla funzione drawImage. Ma come si carica un immagine in javascript.

Il sistema più conosciuto è quella di creare nel DOM html, un elemento e mettere nell'attributo src il percorso del immagine e poi catturarlo con getDocumentById, ma per il canvas non è il più funzionale.

Il mio consiglio è quello di creare un oggetto Image direttamente nel codice javscript, così da essere più gestibile e tenere il DOM pulito con il solo elemento .

let immagine = new Image();
immagine.src = 'laMiaImmagine.jpg';
Enter fullscreen mode Exit fullscreen mode

Abbiamo creato un nuovo oggetto Image() e lo abbiamo salvato nella variabile immagine. Avremmo avuto lo stesso risultato se avessimo usato il metodo document.createElement("img") al posto di new Image().
Nella seconda riga abbiamo attribuito alla proprietà src il percorso di dove si trova l'immagine che vogliamo caricare.

Ma sorge un problema, essendo javascript un linguaggio asincrono, se l'immagine ci mette tanto a caricare, magari perchè è troppo grande, la funzione drawImage riceverà come argomento una variabile non funzionante perchè l'immagine non ha fatto in tempo a caricare e sul canvas non si vedrebbe nulla.

Una soluzione efficente è usare il metodo addEventListener che aggiunge, nel nostro caso, l'evento load. Quest'ultimo, manda in eseguzione la funzione che gli passiamo solo quando l'immagine ha finito di essere caricata.

let immagine = new Image();
immagine.src = 'https://source.unsplash.com/U5rMrSI7Pn4/1920x1280';
immagine.addEventListener('load', () => {
  ctx.drawImage(immagine, 0, 0, 320, 240)
}, false);
Enter fullscreen mode Exit fullscreen mode

Creiamo l'oggetto Image e gli carichiamo l'immagine.
Il metodo addEventListener applicato alla variabile immagine farà partire la funzione contente ctx.drawImage solo quando l'evento 'load', quindi solo quando l'immagine verrà caricata.
Così i problemi di asincronia saranno risolti.

ALTEZZA e LUNGHEZZA

Sicurmante vi sarete accorti che nell'ultimo codice drawImage aveva cinque argomenti e non tre.

  • ctx.drawImage(immagine, x, y, larghezza, altezza)

Abbiamo aggiunto l'altezza e la larghezza perchè l'immagine che abbiamo caricato era un 2400x1600 e se non avessimo adattato l'immagine al canvas, avremmo visto solo una porzione della foto.

Se il nostro scopo è adattare la foto con il canvas possiamo passargli direttamente le proprietà del canvas: width e height, come larghezza e altezza e la x e la y con valore 0.

ctx.drawImage(immagine, 0, 0, canvas.width, canvas.height)
Enter fullscreen mode Exit fullscreen mode

RITAGLIARE (CROP)

Se volessimo ritagliare una porzione rettangolare dell'immagine caricata e disegnarla sul canvas, dovremmo usare anche gli ultimi argomenti che ci permettono di creare una maschera di ritaglio.

  • ctx.drawImage(immagine ,rX, rY, rLarghezza, rAltezza, x, y, larghezza, altezza)

  • immagine: l'oggetto Image()

  • rX, rY: le coordinata dell'immagine da dove partirà il ritaglio

  • rLarghezza, rAltezza: le dimensioni rettangolari del ritaglio

  • x, y: le coordinata di dove verrà posizionati il ritaglio sul canvas

  • larghezza, altezza: altezza e larghezza del ritaglio riferito al canvas

Facciamo un esempio pratico.
Dal immagine sottostante, voglio disegnare a video solo il funghetto di Super Mario.

Alt Photo by Geeky Shots on Unsplash

Il punto di partenza del ritaglio sarà una coordinata relativa all'immagine (non al canvas) con la rX: 220px e la rY: 140px e per comprendere il funghetto dobbiamo creare un rettangolo lungo 140px e alto 110px.

Alt Text

Adesso che abbiamo la porzione ritagliata la posizioniamo sul canvas alle coordinate x: 50 e y:20.

Gli ultimi due valori sono le dimensioni con il quale vuoi fare vedere il tuo ritaglio. Se vuoi che le dimensioni rimangano invariate, rLarghezza deve essere uguale a larghezza e rAltezza devono essere uguali a altezza. Mentre se vogliamo che il ritaglio si raddoppi sul canvas i valori larghezza e Altezza devono essere il doppio dei valori di rLarghezza e rAltezza.
Nel nostro caso rimpiccioliamo il ritaglio dandogli una larghezza di 100 e un'altezza di 80 px.

let immagine = new Image();
immagine.src = 'https://source.unsplash.com/hQ4BQ3wdHsQ/600x400';
immagine.addEventListener('load', () => {
//ctx.drawImage(immagine ,rX, rY, rL, rA, x, y, l, a)
  ctx.drawImage(immagine, 220, 140, 140, 110, 50, 20, 100, 80 )
}, false);
Enter fullscreen mode Exit fullscreen mode

CONCLUSIONE

In questo articolo abbiamo visto come caricare in maniera funzionale un immagine nel canvas e come possiamo creare una maschera di ritaglio con una sola funzione.
Quest'ultima è molto utile qualora volessimo fare degli slideshow o se volessimo dividere vari elementi caricando una solo immagine o (la mia preferita) creare degli sprites per i videogiochi.

Spero che l'articolo ti sia piaciuto Se hai dei consigli, suggerimenti o critiche costruttive lasciami un commento qui sotto oppure contattami trammite i miei social.

Photo by Geeky Shots on Unsplash
Photo by Matthew Henry on Unsplash

Top comments (2)

Collapse
 
florincornea profile image
Cornea Florin

nice work!, to bad that this is not in English

Collapse
 
camizzilla profile image
Roberto

Thanks! I am planning for the translation, but time is short