Canvas Javascript: trasformazioni
Tags: canvas, javascript, scaling, traslating
Published: 2021-02-02 10:58:51

---
title: Canvas Javascript: trasformazioni
published: true
description: Funzioni che scalano, ruotano e traslano il canvas
tags: canvas, javascript, scaling, traslating
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/ssxwhfs33ibtrl4xsrkq.jpg
---

In questo articolo vediamo **le funzioni trasformazione**: traslazione (translating), rotazione e scalatura (scaling).

**Quando si usano le trasformazioni è buona norma salvare lo stato prima del loro utilizzo, per poi ripristinare lo stato salvato all'occorenza**.
Questo perchè con pochi passaggi puoi tornare allo stato iniziale senza dover riscivere tutto a ritroso.

Per capire come funziona il save / restore ho scritto un paragrafetto con un esempio esemplificativo.

##SAVE e RESTORE

Il savataggio _save()_ tiene in memoria gli stili e alcune funzioni, come le funzioni trasfosmazione, scritte in precendenza.

Gli stati salvati vengono impilati uno sopra l'altro e ripristinati dall'ultimo stato salvato.

* `ctx.save`: salva lo stato e lo impila in uno stack
* `ctx.restore`: ripristina il primo stato in cima alla pila dei salvataggi (stack)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/iftrbgtxbq6dat7k8kx2.jpg)

Analizziamo il programma nell'immagine sovrastante.
* nella prima riga salvo lo stato iniziale che sarà il primo stato della nostra pila (stack).
* poi aggiungo il metodo che colorerà gli elementi di blu.
* salvo di nuovo, in questo caso lo stato tiene in memoria lo stile blu e viene impilata sopra il salvataggio precendente.
* Cambiamo ancora colore, questa volta di verde e stampiamo a video un quadrato (1) che sarà di colore verde.
* Con _ctx.restore()_ ripristiniamo il primo salvataggio della pila, quindi l'ultimo stato salvato.
* Ridisegnamo il quadrato (2), questa volta sarà di colore blu come lo stile salvato sullo stato.
* Ripristiniamo l'altro salvataggio di stato, che sarà quello che riporterà il tutto allo stato iniziale.
* come ultimo, disegnamo il quadrato che sarà di colore nero, il colore di default.


# TRASLAZIONE
Questo metodo **sposta sugli assi x e y il canvas di una distanza che gli passeremo come argomento. 
*`ctx.translator(x,y)`. 
Tutti gli oggetti disegnati dopo si sposterando di conseguenza.

```javascript
ctx.fillStyle = "blue";
ctx.fillRect(10, 10, 20, 20);

ctx.translate(100, 100);

ctx.fillStyle = "green";
ctx.fillRect(10, 10, 20, 20);
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/oqcpmoswxpyc1utmtb09.jpg)

Nello script vediamo due quadrati uguali per dimensioni e posizionati nelle stesse coordinate, ma di colori diversi.
Però il secondo quadrato sarà traslato di 100px in orizzonatale e 100px in verticale perchè abbiamo usato la funzione _translate_ per spostare il canvas.

Nel esempio sottostante ho creato un grafico molto semplice che si crea dinamicamente trammite un array di numeri.
Il posizionamento orizzontale è stato fatto trammite un forEach dell'array che spostava i vari oggetti con _traslate_.

{% codepen https://codepen.io/camizzilla/pen/VwKOQRy %}

#ROTAZIONE
Come dice si intuisce dal nome e da quello che abbiamo preso dalla traslazione, questa **funzione ruota di il canvas come perno il punto di origine (0, 0)**.

* ctx.rotate(radianti);

La funzione **_rotate_ prende come valore i radianti e non i gradi**, ma niente paura, sostituendo l'argomento **con la formula _(Math.PI / 180) * gradi_ possiamo tranquillamente usare i gradi**.


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/omgxlbukm36mf8z7xeew.jpg)

Lo script ruota di 45gradi un quadrato, che come perno di rotazione ha il punto di origine del canvas (0,0).

``` javascript 
const grade = 45;
ctx.save();
ctx.rotate( Math.PI / 180 * grade );
ctx.fillRect(200, 0, 60, 60);
ctx.restore()
```

Tutto questo è molto bello, ma poco utile, perché vorremmo scegliere il punto focale dove far ruotare l'oggetto.
In questo caso dobbiamo usare la transizione per scegliere il fulcro del asse di rotazione.

``` javascript 
const grade = 45;
ctx.save();
ctx.translate(130, 130);
ctx.rotate( Math.PI / 180 * grade );
ctx.translate(-130, -130);
ctx.fillRect(100, 100, 60, 60);
ctx.restore()
```
In questo caso abbiamo spostato il punto di rotazione al centro del quadrato, 100 (coordinata) + 30 (metà del lato) = 130, abbiamo ruotato di 45 gradi e poi siamo ritornati alla posizione iniziale usando il traslate con gli stessi valori ma negativi.

{% codepen https://codepen.io/camizzilla/pen/vYyEyRo %}

#SCALATURA
Lo Scaling ci permette di rimpicciolire e ingrandire il canvas e tutto quello che contiene. 

* ctx.scale(x, y);

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vt6kmi5el1ld4swev6dq.jpg)

Il valore di default per entrambi gli argomenti è 1. Questo vuol dire che se volessimo raddoppiare il canvas il valore da passargli sarà 2 e se lo volessimo dimezzare sarà di 0.5 e così via.

``` javascript
ctx.fillStyle = 'blue'
ctx.fillRect(100, 100, 100, 100)

ctx.save();

ctx.scale(2, 2);
ctx.fillStyle = 'red'
ctx.fillRect(100, 100, 100, 100)

ctx.restore();

ctx.save();

ctx.translate(150, 150);
ctx.scale(.5, .5);
ctx.translate(-150, -150);

ctx.fillStyle = 'yellow'
ctx.fillRect(100, 100, 100, 100)

ctx.restore();
```

Il primo quadrato blue è grande 100x100px, il secondo quello rosso ha le stesse dimensioni del primo ma è stato ingrandito del 200%, mentre il terzo, il giallo, è stato rimpicciolito del 50% e come con la funzione rotate abbiamo usato due translate per scegliere il punto di scalatura (si dirà cosi?).

{% codepen https://codepen.io/camizzilla/pen/BaQybPw %}

CONCLUSIONE

In questo articolo vediamo come funzionano le trasformazioni, che potrebbero sembrare ostiche al primo impatto ma che sono abbastanza semplici una volta capito il loro funzionamento.

Ne manca ancora una di trasformazione, quella un po' piu complessa (almeno per me) e quindi gli dedicherò un articolo a parte.

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.